如何利用Composer Scripts实现数据库的自动迁移(Migrations)? (部署自动化)

11次阅读

composer.json 的 “scripts” 中写 migration 脚本需用 “@php artisan migrate –force” 等无交互命令,确保跨平台兼容、环境变量就绪、autoload 已刷新,并通过独立 shell 脚本或多 script 分离控制执行时机与目标库。

如何利用Composer Scripts实现数据库的自动迁移(Migrations)? (部署自动化)

composer.json 里怎么写 migration 脚本?

直接在 "scripts" 段落里加一条命令,调用你项目实际使用的迁移工具(比如 laravelphp artisan migrate 或 Doctrine 的 php vendor/bin/doctrine orm:schema-tool:update --force)。关键不是“能不能写”,而是**命令必须能在当前环境无交互执行**——不能卡在确认提示上。

常见写法示例(Laravel 场景):

"scripts": {     "migrate": [         "@php artisan migrate --force",         "@php artisan db:seed --force"     ] }
  • --force 是必须的,否则生产环境会因未确认而中止
  • 避免写成 "migrate": "php artisan migrate" —— 这样不兼容 windows(PHP 可执行文件路径问题),@php 由 Composer 自动解析为当前 PHP 二进制路径
  • 如果迁移命令依赖环境变量(如 DB_HOST),确保运行 composer run migrate 时这些变量已加载(例如通过 .env 或系统级 export)

为什么 run migrate 有时不生效或报错?

最常见原因是 **当前工作目录不对** 或 **autoload 未刷新**。Composer 脚本默认在 composer.json 所在目录执行,但某些框架(如 symfony)要求在项目根下才能正确加载配置和 autoloader。

  • 运行前先执行 composer dump-autoload --optimize(尤其上线前),否则新写的迁移类可能不被识别
  • 检查 artisanbin/console 是否有可执行权限(linux/macos);Windows 下注意换行符是否为 CRLF 导致解析失败
  • 错误信息如 class 'databaseSeedersDatabaseSeeder' not found,大概率是 autoload 问题,不是脚本本身写错了
  • 不要在脚本里写 cd ./app && php artisan migrate —— Composer 不保证 shell 命令的跨平台行为,应靠项目结构约定而非硬编码路径

如何让 migrate 只在部署时触发,且跳过本地开发?

靠环境变量控制比改脚本更安全。Composer Scripts 本身不内置环境判断,但你可以用 shell 条件或封装一层小脚本。

推荐做法:在 "scripts" 中调用一个独立的 shell 脚本(如 bin/deploy-migrate),内容如下:

#!/bin/sh if [ "$APP_ENV" = "production" ]; then     php artisan migrate --force else     echo "Skipping migrations: APP_ENV is not production" fi
  • 赋予执行权限:chmod +x bin/deploy-migrate
  • composer.json 中引用:"migrate": "bin/deploy-migrate"
  • 这样既清晰隔离逻辑,又避免把条件判断塞进 JSON 字符串里导致转义混乱
  • 注意:docker 部署时,APP_ENV 必须在容器启动时注入,不能只靠 .env 文件(.env 在构建阶段可能未生效)

数据库或分片场景下 scripts 怎么处理?

别试图用一个 composer run migrate 搞定所有库。Composer Scripts 不适合做流程编排,它只是快捷入口。

  • 为不同库定义不同 script,比如 "migrate:tenant""migrate:system",各自指向明确的命令和连接配置
  • 迁移顺序很重要:先主库再从库,先 schema 再 seed。用 "scripts" 数组顺序控制(数组内按序执行),但跨 script 无法保证依赖关系
  • 真正复杂的编排(比如某迁移失败则回滚其他库),应该交给 CI/CD 流水线或专用部署工具(ansible、Deployer),而不是塞进 Composer
  • Doctrine 用户注意:orm:schema-tool:update 是危险操作,生产环境严禁使用;必须用 migrations:migrate 配合显式版本管理

实际部署时,最易被忽略的是迁移命令的超时设置锁机制。比如 Laravel 默认 migration 进程没有超时保护,长迁移可能被 systemd 或 Docker kill 掉;某些数据库(如 mysql)在执行 DDL 时会锁表,若同时跑多个 deploy 实例,可能互相阻塞甚至死锁。这些得在运维层解决,不是改几行 composer.json 就能绕过的。

text=ZqhQzanResources