doctrine migrations 在 symfony 4 中无需为不同数据库调整命令名,但配置、sql 生成和兼容性必须按 mysql/postgresql/sqlite 校准:url 协议头决定驱动与平台,多库需指定 --em,uuid/大小写/索引命名需人工适配,事务与状态表行为因平台而异。

Symfony 4 使用 Doctrine Migrations 管理数据库结构变更,迁移命令本身(如 doctrine:migrations:migrate)**不需要为不同数据库类型(MySQL、PostgreSQL、SQLite)专门调整命令名或主参数**——底层由 Doctrine DBAL 自动适配。但实际使用中,**配置、生成逻辑和 SQL 兼容性必须按数据库类型校准**,否则容易出现“命令跑通却失败”或“生成错误语句”的问题。
数据库连接 URL 必须匹配目标平台特性
Doctrine 根据 DATABASE_URL 的协议头(mysql://、pgsql://、sqlite://)自动加载对应驱动和平台类,进而影响 SQL 生成。关键点:
-
PostgreSQL:URL 必须以
pgsql://开头,且用户名/密码含特殊字符(如@、/)需 URL 编码;不支持autoincrement=true,改用strategy="SEQUENCE"并显式指定sequenceName -
MySQL:支持
options={"autoincrement":true},但注意引擎(ENGINE=InnoDB)和字符集(CHARSET=utf8mb4)不在 Doctrine 默认 diff 范围内,需手动在@ORM\Table中声明 -
SQLite:URL 形如
sqlite:///%kernel.project_dir%/var/data.db,路径需可写;不支持某些 MySQL/PG 特有语法(如ALTER TABLE ... DROP COLUMN在旧版 SQLite 中不可用)
多数据库时必须指定实体管理器(--em 参数)
若项目配置了多个数据库连接(例如主库 + 日志库),doctrine:migrations:diff 默认只对比 default 实体管理器对应的数据库。不加参数会漏生成迁移:
- 生成针对日志库的迁移:
php bin/console doctrine:migrations:diff --em=logging - 执行时也需指定:
php bin/console doctrine:migrations:migrate --em=logging - 检查映射是否生效:
php bin/console doctrine:mapping:info --em=logging
迁移文件内容需适配平台语法差异
Doctrine 自动生成的 SQL 大部分跨平台,但以下情况需人工干预或验证:
-
UUID 字段:MySQL 用
CHAR(36),PostgreSQL 原生支持UUID类型——实体中用type="guid"可兼顾,但生成的addSql()语句可能需微调 -
大小写敏感性:PostgreSQL 表名默认小写,若实体用
@ORM\Table(name="User"),实际建表名为"User"(带引号),而doctrine:schema:update比对时可能因大小写误判为“无变化” -
索引与约束命名:不同平台对索引名长度、字符限制不同(如 MySQL 64 字节,PG 更宽松),Doctrine 生成的哈希名(如
UNIQ_XXXXX)通常安全,但自定义名需检查兼容性
状态表与事务行为因平台而异
Doctrine Migration 的状态跟踪表(doctrine_migration_versions)创建和事务控制依赖底层平台能力:
- PostgreSQL 要求迁移操作必须在事务中执行(
transactional: true是必须项),否则 DDL 语句(如CREATE TABLE)会自动提交,导致部分失败后状态不一致 - SQLite 不支持在事务中执行某些 DDL(如
ALTER TABLE ... ADD COLUMN在旧版本中受限),Doctrine 会降级为分步操作,但需确保 PHP 运行环境启用PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION - MySQL 默认支持事务性 DDL,但大表变更仍建议加
--timeout=300防止锁表超时











