不能。Composer的scripts本身不提供创建目录能力,但可通过调用mkdir -p等系统命令或封装PHP脚本(如bin/mkdir-logs.php)实现,推荐使用post-update-cmd钩子确保目录在安装/更新后始终存在。

Composer 的 scripts 能不能直接创建目录?
不能。Composer 的 scripts 本质是执行 shell 命令,它本身不提供“创建目录”这种内置能力,但可以调用系统命令(如 mkdir)或 PHP 脚本达成目的。关键在于:你得明确日志目录的路径、权限需求和执行时机——比如是安装依赖后创建,还是每次 composer install 都要确保存在。
post-install-cmd 和 post-update-cmd 哪个更合适?
看你的使用场景:post-install-cmd 在首次运行 composer install(且 vendor/ 不存在)时触发;post-update-cmd 在 composer update 或 composer install 重建 vendor/ 时都会执行。如果你希望日志目录在任何完整安装流程后都存在,优先选 post-update-cmd——它覆盖更全,也更符合“确保目录存在”的意图。
- 用
post-install-cmd:适合只部署一次的初始化场景 - 用
post-update-cmd:推荐用于日常开发和 CI/CD,避免因跳过 install 导致目录缺失 - 注意:两个钩子默认不递归创建父目录,
mkdir -p是必须的
怎么写安全可靠的创建命令?
直接写 mkdir logs 很危险:路径相对、权限不可控、失败不报错。正确做法是用绝对路径 + -p + 显式权限设置(尤其在生产环境)。例如:
mkdir -p ${PWD}/storage/logs && chmod 755 ${PWD}/storage/logs
但更健壮的方式是交给 PHP 脚本处理,因为 PHP 能跨平台、可捕获错误、还能检查写入权限:
- 在项目根目录建
bin/mkdir-logs.php,内容为:<?php $dir = __DIR__ . '/../storage/logs'; if (!is_dir($dir)) { if (!mkdir($dir, 0755, true)) { throw new RuntimeException("Failed to create log directory: $dir"); } } echo "Log directory ready: $dir\n"; - 在
composer.json的scripts中添加:"post-update-cmd": [ "php bin/mkdir-logs.php" ] - 确保
storage/目录存在且可写;如果用 Laravel,storage/logs是标准路径,别手误写成logs/
为什么不用 symfony/filesystem?
它可以,但没必要。引入一个组件只为创建一个目录,会增加 autoload 开销和依赖复杂度。Composer 脚本阶段通常不加载全部类(除非显式 require),而 symfony/filesystem 的 Filesystem::mkdir() 需要完整 autoloading 支持。原生 mkdir() 函数足够可靠,且无需额外依赖——除非你已经在项目中重度使用该组件并习惯其 API。
真正容易被忽略的是:脚本执行用户(如 CI 中的 www-data 或 runner)是否对目标路径有写权限。本地测试成功,上线就失败,八成卡在这儿。











