CakePHP 4 の Bake でマイグレーション内容を指定して生成
はじめに
以前に下記投稿で CakePHP 4 での DB マイグレーションの方法をご紹介しました。
- CakePHP 4 のデータベースのマイグレーション機能の使い方 / Twin Turbo Computing
- https://tt-computing.com/cake4-migrations
そこではマイグレーションの生成方法として、データベースから構造を出力する方法をご紹介しています。
ところで CakePHP 4 の bake migration コマンドでは、あるパターンに則したクラス名やカラム名、型などを入力することで、指定内容のマイグレーションを作ることもできます。
今日は CakePHP 4 の bake migration コマンドでテーブルやカラムを指定し、マイグレーションファイルを生成する方法をご紹介します。
- cakephp/app
- 4.1.2
- cakephp/cakephp
- 4.1.6
- cakephp/migrations
- 3.0.0
1. テーブル
1-1. テーブル作成
bin/cake bake migration Create<テーブル名>
# books テーブルを作成
bin/cake bake migration CreateBooks id:primary title:string created modified
追加カラムの指定方法については、後ほど「3. カラム定義の書き方」でご紹介します。
カラム指定を省略してもマイグレファイルは生成されます。
1-2. テーブル削除
執筆時点ではコマンド実行後に手直しが必要です。
詳細は後述しますが、代わりに migration_diff を使うのがいいかと思っています。
bin/cake bake migration Drop<テーブル名>
# books テーブルを削除
bin/cake bake migration DropBooks
このコマンドでは次のようなコードが生成されます。
(コメントなど一部省略)
class DropBooks extends AbstractMigration
{
public function change()
{
$table = $this->table('books');
$table->drop();
}
}
このままマイグレを実行すると、正常終了になるものの、テーブルは削除されません。
下記のように $table->drop() の後に save() を付ける必要があります。
// ↓ save() を追加
$table->drop()->save();
また change() でテーブル削除を行うと rollback 時にエラーになるので、up() と down() に書き換え、さらに down() でのテーブル生成コードを自分で書くことになります。
テーブルを削除する場合は、実際にデータベース上で削除し、
差分抽出の migration_diff コマンドで出力するのがいいかと思います。
# データベースから books テーブルを削除した後に実行
bin/cake bake migration_diff DropBooks
- Dropping a Table (Writing Migrations - Phinx 0.12 Cookbook)
- https://book.cakephp.org/phinx/0/en/migrations.html#dropping-a-table
- Generating a diff between two database states (Migrations - CakePHP Migrations 3.x Cookbook)
- https://book.cakephp.org/migrations/3/en/index.html#generating-a-diff-between-two-database-states
2. カラム
2-1. カラム追加
bin/cake bake migration Add<カラム名>To<テーブル名>
# books に body カラムを追加
bin/cake bake migration AddBodyToBooks body:text
# books に status と slug カラムを追加
bin/cake bake migration AddStatusAndSlugToBooks status:tinyinteger slug:text
2-2. カラム削除
テーブル削除と同様に rollback 時にエラーが出ます。
up() と down() に書き換えるか、migration_diff を使うのがオススメです。
bin/cake bake migration Remove<カラム名>From<テーブル名>
# books テーブルから body カラムを削除
bin/cake bake migration RemoveBodyFromBooks body
2-3. カラム変更
bin/cake bake migration Alter<カラム名>On<テーブル名>
# books テーブルの title カラムを TEXT 型に変更
bin/cake bake migration AlterTitleOnBooks title:text
2-4. テーブル変更(カラム一括追加?)
Alter<テーブル名> でテーブル変更用のマイグレーションが作れるのですが、 実はこのコマンドの使いどころが良く分かっていません(汗)
例えば下記のようにすると、次のようなコードになります。
bin/cake bake migration AlterBooks slug:string price:smallinteger
public function change()
{
$table = $this->table('books');
$table->addColumn('slug', 'string', [
'default' => null,
'limit' => 255,
'null' => false,
]);
$table->addColumn('price', 'smallinteger', [
'default' => null,
'limit' => 6,
'null' => false,
]);
$table->update();
}
ドキュメントには CreateTable と AddField の機能と書かれていますが、
update() なのでちょっと違うような気がするのですが...
- Migrations file name (Migrations - CakePHP Migrations 3.x Cookbook)
- https://book.cakephp.org/migrations/3/en/index.html#migrations-file-name
3. カラム定義の書き方
カラムを指定する際には下記パターンで記述します。
カラム名:型?[長さ]:インデックス:インデックス名
カラム名以外は省略可能で、例えば下記のように書けます。
- id:biginteger:primary
- username:string?[100]:index:MY_USERNAME_INDEX
- old:tinyinteger?
- zipcode:string?[7]
- email:string[100]:unique
# 上記全部入り
bin/cake bake migration CreateUsers id:biginteger:primary username:string?[100]:index:MY_USERNAME_INDEX old:tinyinteger? zipcode:string?[7] email:string[100]:unique
型の後に ? を付けると null が許可になります。
型を省略したり、使用可能なもの以外を指定すると string (varchar) になります。
ただし下記カラム名の場合は例外で、それぞれ指定されている型となります。
Name | Type |
---|---|
id | integer |
created | datetime |
modified | datetime |
updated | datetime |
latitude | decimal |
longitude | decimal |
型には下記を指定できます。
執筆時点では公式ドキュメントに tinyinteger と smallinteger がありませんが、使用可能です。
- boolean
- integer
- tinyinteger
- smallinteger
- biginteger
- float
- decimal
- string
- text
- date
- time
- datetime
- timestamp
- binary
- uuid
コメントや unsigned などの設定は出来ないようです。
- Columns definition (Migrations - CakePHP Migrations 3.x Cookbook)
- https://book.cakephp.org/migrations/3/en/index.html#columns-definition
4. おわりに
コマンド入力でのマイグレーション生成はとても便利です。
僕は VS Code を使っているのですが、その中でターミナル操作ができるので、アプリ切替不要で効率的にマイグレーションを作ることができます。
しかし、このコマンドによる作成が常に最適な方法というわけではありません。
先にも紹介した通り、テーブルやカラムの削除では migration_diff の方がいいと思います。またカラムが多いテーブルの作成も、別手段で作って差分出力した方が早いかもしれませんね。
状況に応じた手段の使い分けは、早さと確実性が求められる開発作業で重要だと考えています。
今回ご紹介したコマンドは使えるようにしつつも、最適な方法を考えながら作業をするのが大切だと思います。