post-create-project-cmd仅在目标模板项目composer.json的"scripts"中明确定义且格式正确(全小写、短横线、数组值)时才触发,由模板作者配置,使用者需先确认该字段存在。

post-create-project-cmd 只在模板项目里生效
这个钩子不是你本地执行 composer create-project 时“想让它干啥就干啥”的开关,而是由你要创建的那个项目(比如 laravel/laravel)自己在它的 composer.json 里声明了才会触发。如果你只是使用者,得先打开目标包的 composer.json 确认有没有 "post-create-project-cmd" 字段。
常见错误现象:composer create-project myorg/my-template 执行完啥也没发生——大概率是 my-template 的 composer.json 根本没配这个字段,或者写成了 PostCreateProject、post_create_project_cmd 这类非法名。
- 必须全小写、短横线分隔:
post-create-project-cmd是唯一合法写法 - 必须定义在目标项目(即被克隆/安装的那个包)的根
composer.json的顶层"scripts"下 - 值必须是数组形式,不能是字符串(否则 Composer 会忽略)
- 脚本在新项目根目录执行,失败则整个
create-project流程中断
怎么让自己的模板项目支持自动初始化
如果你是模板维护者(比如发布一个 Laravel starter kit),需要在你自己的 composer.json 中明确定义:
{
"scripts": {
"post-create-project-cmd": [
"@php -r "echo '✅ Project initialized\n';"",
"php artisan key:generate",
"rm -f .env.example"
]
}
}
注意几点:
- 不要用
cd切目录——执行时 CWD 就是新建项目的根目录 - 避免调用未声明为
require-dev的命令(如phpunit),CI 环境可能没装 - 如果要用 PHP 脚本,记得开头加
require __DIR__ . '/vendor/autoload.php'; - 别依赖
$_SERVER['argv']传参,create-project不传参数给钩子
为什么本地能跑,GitHub Template 或 CI 里不执行
因为 composer create-project 默认不走你本地的全局配置,它只读取目标包自带的 composer.json。如果你 fork 了一个模板但没改它的 composer.json,那无论你怎么调用命令都没用。
另外,某些平台(如 GitHub 的 “Use this template”)根本不经过 Composer,只是 Git clone,自然不会触发任何 Composer 钩子。
- 验证方式:进目标模板仓库,搜
"post-create-project-cmd" - GitLab CI / GitHub Actions 中若用
composer create-project --no-scripts,钩子会被跳过 - 私有模板发布后,记得
composer publish或手动 push 更新 packagist
替代方案:用自定义脚本 + 显式调用更可控
如果你控制不了模板源码,或需要适配多种场景,不如放弃依赖 post-create-project-cmd,改用显式脚本:
{
"scripts": {
"init:project": [
"php artisan key:generate",
"php artisan storage:link",
"chmod -R 755 bootstrap/cache"
]
}
}
然后告诉用户创建完手动跑一句:
composer create-project myorg/my-template my-app && cd my-app && composer init:project
这样逻辑清晰、调试方便,也不受模板是否预置钩子的限制。真正容易被忽略的是:很多人以为钩子能“跨项目生效”,其实它只是一次性绑定在目标 composer.json 里的静态配置,改了模板源码不发新版,下游永远收不到更新。











