動態

詳情 返回 返回

收藏版:Phinx 數據庫遷移完全指南 - 動態 詳情

最近在維護老項目時,又一次用到了 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 會自動將大駝峯命名轉為蛇形文件名,例如 CreateUsersTable20251028123045_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 查看

user avatar ivictor 頭像 huaihuaidehongdou 頭像 ansurfen 頭像 fanudekaixinguo 頭像 songzihuan 頭像 laughingzhu 頭像
點贊 6 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.