ServiceProvider::optimizes(),你可以把生成与删除命令集成到 Laravel 的 optimize 和 optimize:clear 中。
本页以Laravel 包开发为前提,基于 Laravel Framework v13.35.0 确认实现。本页讨论的不是缓存文件的格式,而是注册与运维方面的约定。
区分命令注册与任务注册
commands() 用于注册可以从 Artisan 调用的命令类。optimizes() 则是另一项处理,它把已经可以执行的命令名称注册为优化任务。只调用后者并不会注册命令类。
下面的示例假设包中已经实现了 CacheMetadataCommand 和 ClearMetadataCommand,它们的 $signature 分别为 courier:cache 和 courier:clear-cache。
optimizes() 的参数全部可为 null,因此也可以只注册生成命令或只注册删除命令。不过,你务必要告诉用户通过哪个步骤让已生成的缓存失效。
注册键也是面向用户的约定
ServiceProvider 会把生成命令保存在静态数组 $optimizeCommands 中,把删除命令保存在 $optimizeClearCommands 中。两者都以 key 作为数组键。
如果省略 key,会根据 Provider 的类名生成名称。例如 CourierServiceProvider 会生成 courier。由于只使用类名,位于不同命名空间的同名 Provider 也可能发生冲突。
对同一个键重新注册时,对应一侧的命令会被后注册的值覆盖。如果需要注册多个任务,请指定不同的键。此外,应避免使用 config、routes 等 Laravel 标准任务的键,因为在合并标准任务与包任务时,相同的字符串键同样会被覆盖。
在标准任务之后执行
在所确认的实现中,两个命令都会先把包的注册数组展开到标准任务数组中,然后依次调用。只要使用不冲突的键,包任务就会追加在标准任务之后。
基于这一顺序,生成命令不应重新构建其他标准缓存,而只生成包自己拥有的数据。不要把
optimizes() 当作控制多个包之间依赖顺序的 API。如果需要严格的顺序,请显式地依次排列专用命令。
通过键或命令名称排除
两个命令的--except 都接受以逗号分隔的值。每个值会去掉前后的空白,与任务的键或命令名称匹配的任务会被排除。
cache:clear。cache 是任务的键,并不是包专用的名称。
排除指定只对当次执行生效。它不是禁用 Provider 注册的设置,也不会自动删除之前生成的包缓存。
区分任务的 FAIL 与父命令的退出码
OptimizeCommand 和 OptimizeClearCommand 会用 callSilently() 调用每个任务,并把退出码是否为 0 传给任务显示。正常情况下子命令的输出不会显示,因此要排查原因时,请直接执行专用命令。
在 Laravel v13.35.0 中,两个 handle() 即使子命令返回非零值,也不会把该值作为父命令的返回值。即使屏幕上显示 FAIL,循环也会继续,只要没有异常,父命令的退出码就是 0。另一方面,抛出的异常会在任务显示组件中被重新抛出,因此不会表现出同样的继续执行行为。
如果包的生成是部署的必要条件,请采用可以直接检查子命令退出码的步骤。例如,下面的示例把包任务从批量执行中排除,并在标准任务之后单独直接执行一次。
courier:cache 的失败反映到退出码上,但不会汇总标准任务的非零退出。如果部署需要严格检测标准任务,请逐条执行所需命令并检查各自的退出码。
设计并验证经得起升级的缓存
除了注册之外,还要事先明确命令与读取端各自的职责。- 生成操作在重复执行时,相同的输入应得到相同的状态,并且中途失败时不能启用不完整的数据。
- 删除操作在缓存不存在时也应正常完成,且不能删除用户已发布的配置或持久化数据。
- 生成失败的命令应报告错误并返回非零值。读取端也不应无条件地把损坏的缓存视为正常。
- 更改缓存格式后,要告知用户需要重新生成,并考虑重启长时间运行的进程。
相关页面
包配置的合并与缓存
确认已发布配置的补充与配置缓存重建之间的关系。
使用 Orchestra Testbench 测试 Laravel 包
在测试环境中注册 Provider 和 Artisan 命令。