Laravel包中迁移文件需通过服务提供者loadMigrationsFrom()显式注册路径,命名须含毫秒级时间戳且类名严格匹配,路径必须为绝对路径,否则php artisan migrate无法识别。

发布 Laravel 迁移,本质不是“导出 SQL”,而是把迁移文件作为包的一部分随 Composer 分发,并确保使用者能正确执行 —— 它依赖文件命名、类名、migrations 目录路径三者严格对齐,缺一不可。
包里怎么放迁移文件才被 php artisan migrate 识别
Composer 包中的迁移文件必须放在固定路径,且不能靠软链接或配置“注册”:Laravel 只扫描 database/migrations 目录(项目根目录下),不读取 vendor 里的任何迁移。
- 正确做法是:在包的
src/或database/migrations/下放好迁移文件,然后通过服务提供者(Service Provider)在boot()中调用$this->loadMigrationsFrom(__DIR__.'/../database/migrations'); - 这个路径必须是绝对路径,
__DIR__指向服务提供者所在文件位置;若路径错,php artisan migrate完全看不到这些迁移 - 迁移文件名仍需带毫秒级时间戳(如
2026_05_10_142300_add_tags_to_posts.php),否则执行顺序错乱,且类名必须与文件名完全匹配(大小写、下划线、复数全算)
php artisan vendor:publish 怎么安全导出迁移
直接复制迁移文件到项目 database/migrations 是常见但危险的做法 —— 它破坏了版本隔离,后续包升级时无法自动同步迁移变更。
- 不要用
--tag=migrations一次性发布所有迁移:如果包已发布过 v1.0 的迁移,v1.1 新增了迁移,再运行 publish 会覆盖或重名,导致本地时间戳冲突 - 推荐显式指定发布路径:
php artisan vendor:publish --provider="Vendor\Package\ServiceProvider" --tag="migrations" --force,但仅限首次安装;之后新增迁移应单独手动 cp 或用脚本比对 - 更稳妥的方式是:在包文档中明确列出新增迁移文件名,让用户自己
cp vendor/vendor-name/package/database/migrations/2026_05_12_*.php database/migrations/,并确认不重复
为什么 php artisan migrate 找不到包里的迁移
最常被忽略的是自动加载和路径映射问题:即使服务提供者写了 loadMigrationsFrom(),Laravel 也不会自动发现新迁移,除非该服务提供者已被启用且没被缓存。
- 检查
config/app.php的providers数组是否注册了该包的服务提供者;Laravel 5.5+ 支持 package discovery,但前提是composer.json里有正确的"extra": {"laravel": {"dont-discover": []}}配置 - 运行
php artisan config:clear和composer dump-autoload,否则类未加载,loadMigrationsFrom()调用根本不会执行 - 执行
php artisan migrate:status,看输出里是否出现包迁移的文件名 —— 如果没列出来,说明 Laravel 根本没扫描到它们,不是数据库问题
真正麻烦的不是“怎么放进去”,而是“怎么让不同环境都按同一顺序跑完”。时间戳一旦进 Git,就不可改;包里迁移若和其他包或主项目迁移撞时间戳,只能删一个、补一个 down()、再重跑 —— 这种事在 CI 流水线里最容易暴露,但日志里往往只报 Class not found,得先翻 migrations 表再反查文件。


















