可以獨立使用的遷移包對比后,感覺phinx更接近PHP的使用習慣。
為什么要單獨用?
因為我不想數據庫的遷移文件依賴于某種框架。本來是可以在框架里直接安裝這個包的,但是發現這個包依賴cakephp,而cakephp的函數與thinkphp的env()函數沖突。
官方文檔:Phinx Documentation - 0.16
安裝
新建個空目錄,然后在這個目錄執行:
composer require robmorgan/phinx
安裝好后,在目錄vendor\bin中能找到文件:phinx.bat。
建議:將vendor\bin的路徑加入到系統變量path中,就可以直接用這個命令了。
命令
查看可用命令列表
phinx
查看可用命令的幫助,如:
phinx init --help
初始配置文件
phinx init E:\a\b
假設項目目錄為:E:\a\b\。在目錄下創建配置文件phinx.php和phinx.yml,建議使用.php的文件(因為不用額外裝包),刪除掉phinx.yml。項目目錄不是phinx的安裝目錄。
文件內容如下:
<?phpreturn
['paths' => ['migrations' => '%%PHINX_CONFIG_DIR%%/db/migrations','seeds' => '%%PHINX_CONFIG_DIR%%/db/seeds'],'environments' => ['default_migration_table' => 'phinxlog','default_environment' => 'development','production' => ['adapter' => 'mysql','host' => 'localhost','name' => 'production_db','user' => 'root','pass' => '','port' => '3306','charset' => 'utf8',],'development' => ['adapter' => 'mysql','host' => 'localhost','name' => 'development_db','user' => 'root','pass' => '','port' => '3306','charset' => 'utf8',],'testing' => ['adapter' => 'mysql','host' => 'localhost','name' => 'testing_db','user' => 'root','pass' => '','port' => '3306','charset' => 'utf8',]],'version_order' => 'creation'
];
[path]?節可以指定遷移文件和種子文件所在的目錄,可以指定為數組,如:
'paths' => [
? ? ? ? 'migrations' => [
? ? ? ? ? ? '%%PHINX_CONFIG_DIR%%/db/migrations',
? ? ? ? ? ? 'd:/a/b'
? ? ? ? ],
? ? ? ? 'seeds' => '%%PHINX_CONFIG_DIR%%/db/seeds'
? ? ],
%%PHINX_CONFIG_DIR%% 變量是phinx的內置變量,是配置文件所在的目錄。
[environments]?節為數據庫環境配置:
default_migration_table:指定保存遷移記錄的表名,執行遷移時會生成以這個為表名的表,保存每次執行的記錄。
default_environment:默認使用的環境,development為開發環境,將development節下的數據庫配置好。
創建遷移文件
phinx create SystemDict?--path=E:\a\b\db\migrations -c E:\a\b\phinx.php
phinx create 表名?--path=存放遷移文件的目錄 -c 配置文件路徑(即執行init時創建的文件)
將會在目錄中創建一個遷移文件,名稱類似于:20250830084537_system_dict.php。
如果用的是IDE打開文件,可以看到AbstractMigration是標紅的,這是因為phinx包不在項目目錄中。可以配置下IDE的PHP包含路徑:D:\soft\php\tools\vendor。
這是vscode的配置,我這里用的是Trae。
執行遷移
phinx migrate -c E:\a\b\phinx.php
將命令行的當前目錄切換為:E:\a\b\,可直接執行phinx migrate,不需要指定配置文件。
可以看到執行成功了,但是由于遷移文件是個空的,所以數據庫中沒有任何變化,只是多了一個表:phinxlog。這就是配置文件中指定的表名,非必要時不需要特意去改。表里有了一條記錄:
現在到遷移文件中添加表的定義:
<?phpdeclare(strict_types=1);use Phinx\Migration\AbstractMigration;final class SystemDict extends AbstractMigration
{/*** Change Method.** Write your reversible migrations using this method.** More information on writing migrations is available here:* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method** Remember to call "create()" or "update()" and NOT "save()" when working* with the Table class.*/public function change(): void{// 定義表$table = $this->table('__table_prefix__system_dict', ['id' => false, 'primary_key' => ['id'], 'comment' => '系統字典']);// 定義表字段和索引$table->addColumn('id', 'biginteger', ['limit' => 20, 'null' => false, 'signed' => false, 'identity' => true, 'comment' => '主鍵'])->addColumn('create_time', 'datetime', ['comment' => '創建時間'])->addColumn('update_time', 'datetime', ['comment' => '更新時間'])->addColumn('code', 'string', ['limit' => 100, 'comment' => '字典編碼'])->addColumn('title', 'string', ['comment' => '字典標題,顯示名'])->addIndex('code', ['unique' => true, 'name' => 'idx_dict_code'])->create();}
}
現在再去執行遷移命令,發現什么都沒有變化。這是因為這個文件前一次已經執行過了,在phinxlog表中已經有了記錄。要再次執行這個文件,需要先回滾掉前一次執行的記錄。
為什么要在表定義設置 id=false?
phinx默認情況下會建一個名為id的int類型的主鍵字段,但有時候我們不想用int或是不想用id作為主鍵字段名。這時我們就要自已定義字段了。
回滾
phinx?rollback -c E:\a\b\phinx.php
加了代碼后執行,會得到一個錯誤:
這是因為之前執行時沒有建表,現在回滾導致找不到表。先將代碼中那表的代碼注釋掉,再執行回滾,回滾后再放開注釋掉的代碼。當然也可以手動刪除遷移表中的記錄,但不建議這么干。
每次執行回滾,只會回滾最后一次執行的遷移。如果想一次回滾多個記錄,可以用-t參數指定回滾到的版本,具體可以查看回滾的幫助。
phinx rollback -c E:\a\b\phinx.php ?-t 20250830084537 # 是回滾到這個版本(這個不會回滾,只回滾這個版本之后的所有版本)
phinx rollback -c E:\a\b\phinx.php ?-t 0 # -t 參數指定為0時,將回滾所有版本!!
回滾后再執行下遷移,可以看到表建好了:
查看回滾的幫助
phinx rollback --help
支持的字段類型
以下是各種數據庫都支持的類型
binary
boolean
char
date
datetime
decimal
float
double
smallinteger
integer
biginteger
string
text
time
timestamp
uuid
如果想用特殊類型,參考:Writing Migrations - 0.16,為了通用性,不建議使用特殊的類型。
問題
目前還沒有發現如何統一定義表前綴。