post-install-cmd 总在不该跑时执行是因为 composer 默认在 install 和 update 后均触发该钩子,即使 lock 未变;应通过 composer_command 环境变量区分场景,仅在 update 时执行耗时操作。

post-install-cmd 为什么总在不该跑的时候跑
因为 Composer 默认在 composer install 和 composer update 后都触发 post-install-cmd 和 post-update-cmd,哪怕 composer.lock 没变、依赖完全没更新,脚本照常执行。这不是 bug,是设计行为。
常见后果:本地 composer install 后自动跑 npm run build 或 php artisan config:cache;CI 流水线里重复构建,拖慢部署。
- 检查
composer.json的scripts字段,确认没把同一逻辑重复注册到两个钩子里 - 用
composer install --no-scripts临时跳过,但只是掩耳盗铃 - 真正区分「依赖有变更」和「纯重装」,得靠
COMPOSER_COMMAND环境变量
用 COMPOSER_COMMAND 区分 install 和 update 场景
Composer 2.2+ 在执行脚本时会注入 COMPOSER_COMMAND 环境变量,值为 install 或 update,PHP 脚本里直接 getenv('COMPOSER_COMMAND') 就能判断。
Shell 脚本中则用 $COMPOSER_COMMAND,注意别和 COMPOSER_DEV_MODE 混淆——后者只表示是否启用了 dev 依赖,和脚本触发时机无关。
- 在
post-install-cmd里加判断:只有update才执行耗时操作(如composer dump-autoload --optimize) -
install场景下可跳过 npm 构建、Artisan 缓存等,除非你明确需要「每次重装都刷新」 - 单行 PHP 命令要用引号包裹,比如
php -r "if(getenv('COMPOSER_COMMAND')==='update'){...}",否则 shell 可能提前解析=
autoload_classmap 不是越全越好,反而可能拖慢启动
autoload_classmap 是开发期生成的全量映射数组,生产环境加载它要反序列化几 MB 数据,而一次请求通常只用其中不到 5% 的类。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
它只在以下情况真正生效:composer install --no-dev --optimize-autoloader(二者必须同时用),且项目没显式配置 "classmap": [...]。
- 删掉
composer.json中无用的classmap条目,比如"tests/"、"docs/" - PSR-4 前缀要精简,避免重叠或冗长路径,否则优化后仍会触发大量
stat()调用 - 若必须用 classmap(如动态拼类名),改用
class_alias()或require_once关键文件,别靠 autoload 抗压
OPcache + APCu 是 classmap 的真正加速器
光有 vendor/composer/autoload_classmap.php 文件还不够——每次请求仍要读取、反序列化。必须让 OPcache 缓存这个文件内容,APCu 缓存其解析后的数组结构。
opcache.validate_timestamps=0 必须关掉,否则每次请求都重新读磁盘;"apcu-autoloader": true 要写进 composer.json 的 config 段,并确认 apcu.enable_cli=1 已启用(FPM 下才生效)。
- 验证 APCu 是否命中:
php -r "var_dump(apcu_fetch('composer:autoload'));" - 不要 preload 整个
vendor/,只预加载核心框架类(如LaravelIlluminateFoundationApplication) - preload 文件里禁止
new、class_exists()等运行时检查,只允许require或include
最容易被忽略的是:classmap 的完整性依赖于命名空间声明末尾带反斜杠(如 "App\": "app/"),少一个转义就导致部分类进不了映射,优化后反而报 Class not found —— 这不是脚本没跑,是映射本身漏了。










