Lzh on GitHub

配置

当您使用 Init 命令初始化项目时,Phinx 会在您项目的根目录中创建一个默认文件。默认情况下,此文件使用 YAML 数据序列化格式,但您可以使用 --format 命令行选项来指定 yaml、yml、json 或 php 格式。

当您使用 Init 命令初始化项目时,Phinx 会在您项目的根目录中创建一个默认文件。默认情况下,此文件使用 YAML 数据序列化格式,但您可以使用 --format 命令行选项来指定 yamlymljsonphp 格式。

如果给定了 --configuration 命令行选项,Phinx 将加载指定的文件。否则,它将尝试查找 phinx.phpphinx.jsonphinx.ymlphinx.yaml,并加载找到的第一个文件。更多信息请参见命令章节。

请记得将配置文件存放在 Web 服务器上无法公开访问的目录之外。该文件包含您的数据库凭据,可能会被意外地以纯文本形式提供给外界。

请注意,JSON 和 YAML 文件是被解析的,而 PHP 文件是被包含 (included) 的。这意味着:

  • 它必须返回一个配置项数组。
  • 变量作用域是局部的,也就是说,您需要显式声明您的初始化文件读取或修改的任何全局变量。
  • 其标准输出被抑制。
  • 与 JSON 和 YAML 不同,您可以省略环境连接详情,而是指定 connection,其中必须包含一个已初始化的 PDO 实例。当您希望迁移与您的应用程序交互和/或共享相同的连接时,这非常有用。但是,请记住也要传递数据库名称,因为 Phinx 无法从 PDO 连接中推断出这一点。
$app = require 'app/phinx.php';
$pdo = $app->getDatabase()->getPdo();

return [
    'environments' => [
        'default_environment' => 'development',
        'development' => [
            'name' => 'devdb',
            'connection' => $pdo
        ]
    ]
];

迁移路径

第一个选项指定了您的迁移目录的路径。Phinx 默认使用 %%PHINX_CONFIG_DIR%%/db/migrations

%%PHINX_CONFIG_DIR%% 是一个特殊令牌,会自动被替换为您的 phinx 配置文件所在的根目录。

要覆盖默认的 %%PHINX_CONFIG_DIR%%/db/migrations,您需要在配置中添加以下内容:

paths:
    migrations: /your/full/path

您也可以通过在配置中使用数组来提供多个迁移路径:

paths:
    migrations:
        - application/module1/migrations
        - application/module2/migrations

可以通过为每个迁移路径添加一个键来指定类的命名空间:

paths:
    migrations:
        App\Module1\Migrations: application/module1/migrations
        App\Module2\Migrations: application/module2/migrations

您也可以在路径中使用 %%PHINX_CONFIG_DIR%% 令牌。

paths:
    migrations: '%%PHINX_CONFIG_DIR%%/your/relative/path'

迁移是使用 glob 捕获的,因此您可以为多个目录定义一个模式。

paths:
    migrations: '%%PHINX_CONFIG_DIR%%/module/*/{data,scripts}/migrations'

自定义迁移基类

默认情况下,所有迁移都将继承自 Phinx 的 AbstractMigration 类。通过在配置中设置 migration_base_class,可以将其更改为一个继承自 AbstractMigration 的自定义类:

migration_base_class: MyMagicalMigration

种子路径

第二个选项指定了您的种子目录的路径。Phinx 默认使用 %%PHINX_CONFIG_DIR%%/db/seeds

%%PHINX_CONFIG_DIR%% 是一个特殊令牌,会自动被替换为您的配置文件所在的根目录。

要覆盖默认的 %%PHINX_CONFIG_DIR%%/db/seeds,您需要在 yaml 配置中添加以下内容:

paths:
    seeds: /your/full/path

您也可以通过在配置中使用数组来提供多个种子路径:

paths:
    seeds:
        - /your/full/path1
        - /your/full/path2

您也可以在路径中使用 %%PHINX_CONFIG_DIR%% 令牌。

paths:
    seeds: '%%PHINX_CONFIG_DIR%%/your/relative/path'

可以通过为每个种子路径添加一个键来指定类的命名空间:

paths:
    seeds:
        App\Module1\Seeds: application/module1/seeds
        App\Module2\Seeds: application/module2/seeds

自定义 Seeder 基类

默认情况下,所有 seeder 类都将继承自 Phinx 的 AbstractSeed 类。通过在配置中设置 seed_base_class,可以将其更改为一个继承自 AbstractSeed 的自定义类:

seed_base_class: MyMagicalSeeder

自定义迁移模板

可以通过在配置文件中定义模板文件路径来使用自定义迁移模板:

templates:
    file: src/templates/customMigrationTemplate.php

自定义 Seeder 模板

可以通过在配置文件中定义模板文件路径来使用自定义 Seeder 模板:

templates:
    seedFile: src/templates/customSeederTemplate.php

环境

Phinx 的一个关键特性是支持多个数据库环境。您可以使用 Phinx 在开发环境中创建迁移,然后在生产环境中运行相同的迁移。环境是在 environments 嵌套集合下指定的。例如:

environments:
    default_migration_table: phinxlog
    default_environment: development
    production:
        adapter: mysql
        host: localhost
        name: production_db
        user: root
        pass: ''
        port: 3306
        charset: utf8mb4
        collation: utf8mb4_unicode_ci

这将定义一个名为 production 的新环境。

当多个开发人员在同一个项目上工作,并且每个人都有不同的环境(例如,遵循 <环境类型>-<开发者名称>-<机器名称> 这样的约定),或者当您需要为不同目的(分支、测试等)设置独立的环境时,可以使用环境变量 PHINX_ENVIRONMENT 来覆盖 yaml 文件中的默认环境:

export PHINX_ENVIRONMENT=dev-`whoami`-`hostname`

迁移表

为了跟踪某个环境的迁移状态,Phinx 会创建一个表来存储这些信息。您可以通过配置 default_migration_table 来自定义此表的创建位置,该配置将作为所有环境的默认值:

environment:
    default_migration_table: phinxlog

如果省略此字段,则默认为 phinxlog。对于支持它的数据库(如 Postgres),可以在模式(schema)名称前加上一个点分隔符(.)。例如,phinx.log 将在 phinx 模式下创建 log 表,而不是在 public(默认)模式下创建 phinxlog 表。

您也可以为每个环境单独指定 migration_table。任何未指定 migration_table 的环境将回退使用在顶层定义的 default_migration_table。下面是一个使用示例:

environment:
    default_migration_table: phinxlog
    development:
        migration_table: phinxlog_dev
        # ... development 的其余设置
    production:
        # ... production 的其余设置

在上面的示例中,development 环境将在 phinxlog_dev 表中查找迁移状态,而 production 环境将使用 phinxlog 表。

表前缀和后缀

您可以定义表前缀和表后缀:

environments:
    development:
        ....
        table_prefix: dev_
        table_suffix: _v1
    testing:
        ....
        table_prefix: test_
        table_suffix: _v2

套接字连接

当使用 MySQL 适配器时,也可以使用套接字(socket)代替网络连接。套接字路径通过 unix_socket 配置:

environments:
    default_migration_table: phinxlog
    default_environment: development
    production:
        adapter: mysql
        name: production_db
        user: root
        pass: ''
        unix_socket: /var/run/mysql/mysql.sock
        charset: utf8

外部变量

Phinx 会自动获取任何以 PHINX_ 为前缀的环境变量,并使其在配置文件中作为一个令牌(token)可用。令牌的名称与变量完全相同,但您必须通过在两边用两个 %% 符号包裹来访问它。例如:'%%PHINX_DBUSER%%'。如果您希望将机密的数据库凭据直接存储在服务器上,而不是存储在版本控制系统中,这个功能尤其有用。以下示例可以轻松演示此功能:

environments:
    default_migration_table: phinxlog
    default_environment: development
    production:
        adapter: mysql
        host: '%%PHINX_DBHOST%%'
        name: '%%PHINX_DBNAME%%'
        user: '%%PHINX_DBUSER%%'
        pass: '%%PHINX_DBPASS%%'
        port: 3306
        charset: utf8

数据源名称 (DSN)

Phinx 支持使用数据源名称 (DSN) 来指定连接选项,这在您使用单个环境变量来保存数据库凭据时非常有用。根据底层驱动程序的不同,PDO 有不同的 DSN 格式,因此 Phinx 使用了一种被其他项目(如 Doctrine、Rails、AMQP、PaaS 等)使用的、与数据库无关的 DSN 格式。

<adapter>://[<user>[:<pass>]@]<host>[:<port>]/<name>[?<additionalOptions>]

一个 DSN 至少需要 adapterhostname

  • 如果没有用户名,则不能指定密码。
  • port 必须是一个正整数。
  • additionalOptions 采用查询字符串的形式,并将作为选项数组传递给适配器。
environments:
    default_migration_table: phinxlog
    default_environment: development
    production:
        # 示例数据源名称
        dsn: mysql://root@localhost:3306/mydb?charset=utf8

DSN 被解析后,其值会与已有的连接选项合并。在 DSN 中指定的值绝不会覆盖任何直接作为连接选项指定的值。

environments:
    default_migration_table: phinxlog
    default_environment: development
    development:
        dsn: '%%DATABASE_URL%%'
    production:
        dsn: '%%DATABASE_URL%%'
        name: production_database

如果提供的 DSN 无效,它将被完全忽略。

支持的适配器

Phinx 目前原生支持以下数据库适配器

  • MySQL: 指定 mysql 适配器。
  • PostgreSQL: 指定 pgsql 适配器。
  • SQLite: 指定 sqlite 适配器。
  • SQL Server: 指定 sqlsrv 适配器。

适配器可用的设置如下:

  • adapter: 要使用的适配器名称,例如 pgsql
  • host: 数据库服务器的主机名(或 IP 地址)。
  • port: 数据库服务器的 TCP 端口号。
  • user: 数据库的用户名。
  • pass: 数据库的密码。
  • name: 此环境的数据库名称。对于 SQLite,建议使用绝对路径,不带文件扩展名。
  • suffix: 用于 SQLite 数据库文件的后缀。默认为 .sqlite3
  • schema: 对于 PostgreSQL,允许指定要用于数据库的模式。默认为 public

对于每个适配器,您可以通过在配置对象中设置常量名的小写版本来配置底层 PDO 对象的行为。这适用于 PDO 选项(例如 \PDO::ATTR_CASE 将是 attr_case)和特定于适配器的选项(例如对于 MySQL,您可以将 \PDO::MYSQL_ATTR_IGNORE_SPACE 设置为 mysql_attr_ignore_space)。请查阅 PDO 文档以了解允许的属性及其值。

例如,要设置上述示例选项:

$config = [
    "environments" => [
        "development" => [
            "adapter" => "mysql",
            # 其他适配器设置
            "attr_case" => \PDO::ATTR_CASE,
            "mysql_attr_ignore_space" => 1,
        ],
    ],
];

默认情况下,Phinx 设置的唯一属性是 \PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION。不建议覆盖此设置。

MySQL

MySQL 适配器有一个不幸的限制,即某些操作会导致隐式提交,无论事务状态如何。值得注意的是,此列表包括 CREATE TABLEALTER TABLEDROP TABLE,这些是 Phinx 将运行的最常见操作。这意味着与其他适配器在迁移失败时会尝试优雅地回滚事务不同,如果 MySQL 的迁移失败,它可能会使您的数据库处于部分迁移的状态。

SQLite

声明一个 SQLite 数据库使用简化的结构:

environments:
    development:
        adapter: sqlite
        name: ./data/derby
        suffix: ".db"    # 默认为 ".sqlite3"
    testing:
        adapter: sqlite
        memory: true     # 将 memory 设置为 *任何* 值都会覆盖 name

从 PHP 8.1 开始,只要 open_basedir 未设置,SQLite 适配器就支持通过使用 URI 方案来支持 cachemode 查询参数。

environments:
    testing:
        adapter: sqlite
        name: my_app
        mode: memory     # 决定新数据库是只读打开、读写打开、读写并创建(如果不存在),还是一个纯内存数据库,从不与磁盘交互。
        cache: shared    # 决定新数据库是使用共享缓存模式还是私有缓存打开。

SQL Server

当使用 sqlsrv 适配器并连接到命名实例时,您应该省略 port 设置,因为 SQL Server 会自动协商端口。此外,省略 charset: utf8 或将其更改为 charset: 65001,这对应于 SQL Server 的 UTF8。

自定义适配器

您可以通过向 AdapterFactory 注册一个 Phinx\Db\Adapter\AdapterInterface 的实现来提供自定义适配器:

$name  = 'fizz';
$class = 'Acme\Adapter\FizzAdapter';

AdapterFactory::instance()->registerAdapter($name, $class);

适配器可以在调用 $app->run() 之前的任何时候注册,该调用通常由 bin/phinx 执行。

模板

您可以通过多种方式覆盖 Phinx 生成模板的方式:

  • file - 要使用的备用文件的路径。
  • class - 用于模板的类,必须实现 Phinx\Migration\CreationInterface 接口。
  • style - 用于模板的样式,可以是 changeup_down,如果未设置,则默认为 change

您应该只使用这些选项中的一个。这些选项可以通过向创建命令传递命令行选项来覆盖。在配置文件中的使用示例是:

templates:
    style: up_down

别名

模板创建类名可以设置别名,并与创建命令--class 命令行选项一起使用。

设置别名的类仍然需要实现 Phinx\Migration\CreationInterface 接口。

aliases:
    permission: \Namespace\Migrations\PermissionMigrationTemplateGenerator
    view: \Namespace\Migrations\ViewMigrationTemplateGenerator

版本顺序

在回滚或打印迁移状态时,Phinx 会根据 version_order 选项对已执行的迁移进行排序,该选项可以有以下值:

  • creation (默认值): 迁移按其创建时间排序,这也是其文件名的一部分。
  • execution: 迁移按其执行时间(也称为开始时间)排序。

引导路径

您可以提供一个 bootstrap PHP 文件的路径,该文件将在任何 phinx 命令运行之前被包含。请注意,设置外部变量来修改配置将不起作用,因为此时配置已经被解析了。

paths:
    bootstrap: 'phinx-bootstrap.php'

在引导脚本中,以下变量将可用:

/**
 * @var string $filename 由配置提供的文件名
 * @var string $filePath 文件的绝对真实路径
 * @var \Symfony\Component\Console\Input\InputInterface $input 正在执行的命令的输入对象
 * @var \Symfony\Component\Console\Output\OutputInterface $output 正在执行的命令的输出对象
 * @var \Phinx\Console\Command\AbstractCommand $context 正在执行的命令对象
 */

功能标志

对于一些破坏性变更,Phinx 提供了一种选择不使用新行为的方式。以下标志可用:

  • unsigned_primary_keys: Phinx 是否应将主键创建为无符号整数? (默认: true)
  • column_null_default: Phinx 是否应默认将列创建为可为 null? (默认: true)

由于 MySQL 的 TIMESTAMP 字段不支持 2038-01-19 之后的日期,您可以选择对由 addTimestamps() 函数创建的字段使用 DATETIME 字段类型:

  • add_timestamps_use_datetime: Phinx 是否应将 created_at 和 updated_at 字段创建为 datetime? (默认: false)
feature_flags:
    unsigned_primary_keys: false

这些值也可以通过修改 Phinx\Config\FeatureFlags 类上的类字段来设置,将标志名称转换为驼峰命名法 (camelCase),例如:

Phinx\Config\FeatureFlags::$unsignedPrimaryKeys = false;