Composer 钩子脚本实操:让你的项目模板开箱即用

做 PHP 开发,composer installcomposer require 基本是日常,但 Composer 的钩子脚本,估计不少同学都没怎么用过。

最近想弄一个项目模板,让其他人可以通过 composer create-project 一键安装,安装完自动把 .env.example 复制成 .env、生成密钥、提示下一步操作。折腾了一番,踩了不少坑,今天把经验整理出来,希望能帮到有同样需求的同学。

先把坑填上:type 必须是 project

这个坑我踩得很惨——模板写好了,composer create-project 却死活装不了。

问题出在 composer.jsontype 字段。想用 create-project 安装,这个字段必须是 project,填 library 的话只能 composer require

建模板其实很简单:

1
2
mkdir my-project-template && cd my-project-template
composer init

composer init 的时候注意两点:一是 Package name 要用「作者名/包名」的格式,比如 l1n6yun/my-project-template;二是 Project typeproject

生成的 composer.json 最小结构:

1
2
3
4
5
6
7
{
"name": "l1n6yun/my-project-template",
"type": "project",
"require": {
"php": ">=7.4"
}
}

然后在模板里放好 .env.exampleindex.php 这些基础文件,一个能被 create-project 识别的模板就有了。

三个钩子的区别,搞清楚就够用了

Composer 钩子有好几个,但做项目模板主要用这三个:post-root-package-installpost-autoload-dumppost-create-project-cmd

post-root-package-install:模板刚下载完

用户执行 composer create-project,Composer 把你的模板下载下来,还没开始装依赖(此时 vendor 目录还不存在),这个钩子就触发了。

最适合干的事:复制 .env.example.env

为什么?因为这时候模板文件刚到位,.env 还不存在,是复制的最佳时机,而且不用依赖任何包,执行最快。Laravel 官方也是这么干的。

1
2
3
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
]

用 PHP 的 copy() 函数,Windows、Linux、Mac 通用,不用管系统命令的差异。

post-autoload-dump:vendor/autoload.php 生成后

触发时机:composer installcomposer updatecomposer dump-autoload,以及 create-project 安装依赖完成后。

简单说,依赖装好了,需要用到 vendor 里的类了,这个钩子就派上用场了。

常见用途:框架的插件自动发现、生成缓存、初始化需要加载类的操作。

1
2
3
"post-autoload-dump": [
"@php artisan package:discover --ansi"
]

注意:别用这个钩子复制 .env,这时候依赖都装完了,再复制环境文件可能会出问题。

post-create-project-cmd:全部搞定,最后一步

create-project 流程全部结束后触发,依赖装好了、自动加载器也生成了,项目完全就绪。

最适合做的事:给用户友好提示、执行最终初始化操作。

1
2
3
4
"post-create-project-cmd": [
"@php artisan key:generate --ansi",
"echo 项目安装成功!执行 php artisan serve 启动服务~"
]

一套完整配置,直接拿去用

把三个钩子组合起来,就是一套完整的脚本配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"name": "l1n6yun/my-project-template",
"type": "project",
"require": {
"php": ">=7.4"
},
"scripts": {
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-autoload-dump": [
"@php artisan package:discover --ansi"
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi",
"echo 项目安装成功!"
]
}
}

最后说几个注意点

  1. 执行顺序post-root-package-installpost-autoload-dumppost-create-project-cmd,顺序不能乱,否则依赖找不到、文件生成失败都会出现。

  2. 复制 .env:用 post-root-package-install,这是官方推荐的做法。

  3. @php 是什么:Composer 的内置命令,表示用当前项目的 PHP 解释器,避免系统 PHP 版本和项目要求不一致。

  4. 本地测试:模板建好后,执行 composer create-project ./my-project-template test-project,看 .env 是否自动生成、提示信息是否正常显示。

  5. 包还没发布怎么办:如果模板还在开发阶段,没有发布到 Packagist,可以用 --repository-url 参数指定仓库地址。比如你的模板托管在 GitHub,可以这样安装:

    1
    composer create-project l1n6yun/my-project-template my-app --repository-url=https://github.com/l1n6yun/my-project-template.git

这样就能直接从 Git 仓库拉取安装,不用先发布包。本地测试也可以用这个方式,把地址换成本地路径就行。

Composer 的钩子其实不难理解,关键是搞清楚每个钩子的触发时机,按需分配操作就行。掌握这三个,项目模板的自动化初始化就搞定了,用户的安装体验也能上一个台阶。

有问题欢迎评论区交流~