最近在維護老項目時,又一次用到了 Phinx。
這個工具我已經用了很多年,幾乎每個項目都會用上它。它屬於那種平時不常用,但每個項目都離不開 的工具。
問題在於,它用得不頻繁,每次寫遷移腳本時總會忘記某個參數怎麼寫、某個字段該用什麼類型。
這些當然可以去查官方文檔,但 Phinx 的文檔雖然內容齊全,卻總讓我覺得信息分散、查起來不夠順手。
於是,我乾脆花點時間,把自己常用的命令、配置方式、字段類型和參數説明都系統地整理了一遍。
一方面方便自己查閲,另一方面也希望能幫到同樣在項目中使用 Phinx 的開發者。
如果你也在 PHP 項目裏用 Phinx 管理數據庫遷移,這篇文章或許能成為你的「快捷參考手冊」。
前期配置
安裝 Phinx
composer require robmorgan/phinx
初始化配置
執行初始化命令:
vendor/bin/phinx init
該命令會在項目根目錄下生成一個 phinx.php 配置文件。
配置文件中:
-
paths用於指定遷移腳本與填充腳本的路徑; -
environments用於定義不同環境(例如開發、測試、生產)的數據庫配置; - 若執行遷移命令時不指定環境,則默認使用
default_environment指定的環境。
環境配置與 .env 支持
為了統一管理數據庫配置,我習慣用 .env 文件來維護連接信息。
但由於 phinx 腳本並不運行在 PHP 框架生命週期內,常見的 .env 加載方式(如 Laravel 的)無法直接使用,因此我通常會額外安裝 vlucas/phpdotenv:
composer require vlucas/phpdotenv
然後在 phinx.php 中添加如下配置:
<?php
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
return [
"paths" => [
"migrations" => "database/migrations",
"seeds" => "database/seeds"
],
"environments" => [
"default_migration_table" => "phinxlog",
"default_environment" => "production",
"production" => [
"adapter" => "mysql",
"host" => $_SERVER['DB_HOST'],
"name" => $_SERVER['DB_NAME'],
"user" => $_SERVER['DB_USER'],
"pass" => $_SERVER['DB_PASS'],
"port" => $_SERVER['DB_PORT'],
"charset" => $_SERVER['DB_CHARSET']
]
]
];
常用命令
創建遷移文件
vendor/bin/phinx create 遷移名稱
Phinx 會自動根據時間戳與名稱生成遷移文件。
命名建議保持統一規範:
- 創建表:
Create + 表名→ 例如CreateUsersTable - 修改表:
Modify + 表名 + 操作→ 例如ModifyUsersAddStatus - 刪除表:
Delete + 表名→ 例如DeleteOldLogsTable
Phinx 會自動將大駝峯命名轉為蛇形文件名,例如CreateUsersTable→20251028123045_create_users_table.php
執行遷移
沒什麼好説的,執行這個命令即可執行遷移
vendor/bin/phinx migrate
參數説明:
-
-e:指定環境(默認production) -
-t:指定執行到的版本號(不傳則執行到最新) -
--dry-run:僅打印 SQL 而不實際執行
注意:-t 不是隻執行單個版本,而是順序執行直到目標版本號為止。
設置斷點(Breakpoint)
生產環境中執行遷移後,建議立刻設置斷點。
斷點能防止誤操作導致大規模回滾。
vendor/bin/phinx breakpoint
參數:
-
-e環境名 -
-t版本號 -
-r刪除斷點
回滾遷移
慎用!
遷移的回滾會撤銷數據庫結構更改,例如刪除表或字段,表中數據會全部丟失。
生產環境不建議直接回滾,而是通過新的遷移來完成結構恢復。
vendor/bin/phinx rollback
參數説明:
-
-e環境名 -
-t指定版本號(或0回滾全部) -
-d按日期回滾(YYYYmmddHHiiss) -
-f強制回滾(忽略斷點) -
--dry-run僅打印 SQL 不執行
查看狀態
用於查看遷移執行狀態,確認哪些遷移尚未執行。
vendor/bin/phinx status
參數説明:
-e:環境名
創建填充(Seeder)
vendor/bin/phinx seed:create 填充名稱
命名建議使用表名 + 填充描述,例如:
UsersAddDemoDataSeeder
執行填充:
vendor/bin/phinx seed:run
參數:
-
-e指定環境 -
-s指定執行的 Seeder,可多次傳入
遷移腳本詳解
支持的字段類型
Phinx 在 MySQL 下支持的字段類型如下:
| 類型 | MySQL 類型 | 必需參數 | 説明 |
|---|---|---|---|
smallinteger |
SMALLINT | — | 小整數 |
integer |
INT | — | 常規整數 |
biginteger |
BIGINT | — | 大整數 |
float |
FLOAT | — | 單精度浮點數 |
double |
DOUBLE | — | 雙精度浮點數 |
decimal |
DECIMAL(M,D) | precision,scale |
定點小數(金額等) |
bit |
BIT | — | 位字段 |
boolean |
TINYINT(1) | — | 布爾值(0/1) |
char |
CHAR(n) | limit |
定長字符串 |
string |
VARCHAR(n) | limit |
可變長度字符串 |
text |
TEXT | — | 文本 |
enum |
ENUM(...) | values |
枚舉類型 |
set |
SET(...) | values |
集合類型 |
uuid |
CHAR(36) | — | UUID字符串 |
date |
DATE | — | 日期 |
time |
TIME | — | 時間 |
datetime |
DATETIME | — | 日期與時間 |
timestamp |
TIMESTAMP | — | 時間戳 |
binary |
BINARY(n) | limit |
定長二進制數據 |
blob |
BLOB | — | 二進制大對象 |
tinyblob |
TINYBLOB | — | 小型二進制 |
mediumblob |
MEDIUMBLOB | — | 中型二進制 |
longblob |
LONGBLOB | — | 超大二進制 |
json |
JSON | — | JSON 數據類型 |
常用字段參數
| 參數名 | 類型 | 説明 |
|---|---|---|
limit / length |
int | 長度或字節限制 |
default |
mixed | 默認值 |
null |
bool | 是否允許為 NULL |
after |
string | 放置在某個字段之後(或 \Phinx\Db\Adapter\MysqlAdapter::FIRST ) |
comment |
string | 字段註釋 |
precision |
int | 小數總位數 |
scale |
int | 小數位數 |
signed |
bool | 是否允許負數 |
values |
array/string | 枚舉或集合可選值,英文逗號隔開的字符串或數組 |
identity |
bool | 是否自增(需搭配 null:false) |
各種操作調用代碼
如果對錶格形式不感興趣,可以直接通過以下完整遷移腳本理解字段定義方式。
<?php
declare(strict_types=1);
use Phinx\Db\Adapter\MysqlAdapter;
use Phinx\Migration\AbstractMigration;
final class CreateTable 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
{
// 前置説明:
// create() 操作: 表不存在的情況下,創建表,並保存字段操作
// update() 操作: 表存在的情況下,變更表,並保存字段操作
// 所有的操作記得到最後一定需要對構建的表對象執行保存操作,否則不會執行
// 判斷表是否存在: $this->hasTable('table_name');
// 刪除表: $this->table('table_name')->drop()->save();
// 構建表
$table = $this->table('table_name', ['id' => 'table_id', 'comment' => '這是 table 表']);
// 第二個參數字段,可不傳,主要用於在 create() 時構建表級的基本信息
// 支持的參數:
// id: 主鍵 ID 列,傳入字符串或者布爾類型
// 如果是字符串:按照字符串內容創建自增主鍵
// 如果是false:不自動創建主建
// 如果不傳:自動創建名稱為 id 的自增主鍵
// comment: 設置表的註釋
// row_format: 設置表的行格式(MySQL 特有,例如 DYNAMIC, COMPACT, REDUNDANT, COMPRESSED)
// engine: 設置表的存儲引擎(MySQL 特有,例如 InnoDB, MyISAM, MEMORY)
// collation: 設置字符集的排序規則,默認 utf8mb4_unicode_ci
// signed: 整數類型是否允許負數,默認 false
// limit: 設置主鍵最大長度
// 變更表註釋
$table->changeComment('這是 table 表新的註釋');
// 更改主鍵,可以設置多個列組聯合主鍵
$table->changePrimaryKey(['new_id']);
// 重命名錶
$table->rename('new_table_name');
// 檢查字段是否存在:$table->hasColumn('username');
// 重命名字段
$table->renameColumn('老字段名', '新字段名');
// 刪除字段
$table->removeColumn('字段名');
// 添加字段
$table->addColumn('字段名', '類型', ['參數'])
->addColumn('avatar', 'string', ['comment' => '頭像', 'null' => true, 'after' => 'name'])
->addColumn('created_at', 'integer', ['comment' => '創建時間', 'null' => false, 'limit' => MysqlAdapter::INT_BIG]);
// 類型:
// 很多不必要或可以簡化定義的類型,例如數字方面,可以全部都設置為 `integer` 通過 `limit` 參數設置長度即可自動創建對應類型
// 以下是支持的類型:
// smallinteger(SMALLINT): 小整數
// integer(INT): 常規整數
// biginteger(BIGINT): 大整數
// float(FLOAT): 單精度浮點數
// double(DOUBLE): 雙精度浮點數
// decimal(DECIMAL(M,D)): 定點小數,必須攜帶 `precision` 與 `scale` 參數
// bit(BIT): 位字段
// boolean(TINYINT(1)): 布爾值(0/1)
// char(CHAR(n)): 定長字符串,必須攜帶 `limit` 參數
// string(VARCHAR(n)): 可變長度字符串,必須攜帶 `limit` 參數
// text(TEXT): 文本
// enum(ENUM(...)): 枚舉類型,必須攜帶 `values` 參數
// set(SET(...)): 集合類型,必須攜帶 `values` 參數
// uuid(CHAR(36)): UUID字符串
// date(DATE): 日期(YYYY-MM-DD)
// time(TIME): 時間(HH:MM:SS)
// datetime(DATETIME): 日期與時間
// timestamp(TIMESTAMP): 時間戳
// binary(BINARY(n)): 定長二進制數據,必須攜帶 `limit` 參數
// blob(BLOB): 二進制大對象
// tinyblob(TINYBLOB): 小型二進制
// mediumblob(MEDIUMBLOB): 中型二進制
// longblob(LONGBLOB): 超大二進制
// json(JSON):JSON 數據類型
// 參數:
// 以下是支持的參數:
// limit / length: 長度,int 類型,內容跟隨字段類型變化
// default: 默認值,類型根據字段類型變化
// null: 是否允許為 null,bool 類型,true 或者 false
// after: 指定字段應該放在哪個列之後,string 類型傳遞列名,或者 \Phinx\Db\Adapter\MysqlAdapter::FIRST
// comment: 字段註釋,string 類型
// precision: 結合 scale 設置小數精度,int 類型
// scale: 結合 precision 設置小數精度,int 類型
// signed: 是否允許負數,bool 類型
// values: 枚舉類型,可以是英文逗號分隔的string,或array
// identity: 數字類型自增長,bool類型,需要設置 null:false
// 修改字段
$table->changeColumn('字段名', '類型', ['參數']);
// 設置索引
$table->addIndex(['字段名']);
// 刪除索引
$table->removeIndex(['字段名']);
// 或者
$table->removeIndexByName('索引名');
}
}
填充腳本(Seeder)示例
<?php
declare(strict_types=1);
use Phinx\Seed\AbstractSeed;
class TableAddDemoDataSeeder extends AbstractSeed
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* https://book.cakephp.org/phinx/0/en/seeding.html
*/
public function run(): void
{
// 構建數據
$data = [
[
'body' => 'foo',
'created' => date('Y-m-d H:i:s'),
],
[
'body' => 'bar',
'created' => date('Y-m-d H:i:s'),
]
];
// 構建表
$table = $this->table('table_name');
// 添加數據,並保存
$table->insert($data)
->saveData();
// 清空表中的所有數據
$table->truncate();
}
}
老項目遷移接入
如果你是從已有數據庫切換到 Phinx,可使用 phinx-migrations-generator 自動生成遷移文件。
composer require odan/phinx-migrations-generator --dev
它會直接讀取現有的 phinx.php 配置,無需額外設置。
執行以下命令即可生成當前數據庫結構的遷移文件:
vendor/bin/phinx-migrations generate
最後
Phinx 是一個非常輕量卻強大的遷移工具,適用於幾乎所有獨立 PHP 項目。
寫這篇筆記的初衷很簡單——自己每次都要重新翻文檔太麻煩了,不如干脆整理一份系統化的版本。
如果你也有相同的困擾,希望這篇文章能讓你變得方便一些
覺得有用的話,別忘了收藏這篇文章~
更多內容可以在我的網站 https://hejunjie.life 查看