composer 的 bin 字段用于声明包内可执行脚本,安装时自动在 vendor/bin/ 下创建符号链接;需确保脚本存在、有 x 权限、shebang 正确(如 #!/usr/bin/env php),且路径精确匹配。

bin 字段是让 Composer 安装后自动软链可执行文件
Composer 的 bin 字段本身不“执行”任何操作,它只是告诉 Composer:“这个包里有可执行脚本,安装时请把它们软链接到项目根目录的 vendor/bin/ 下”。你写 "bin": ["phpunit", "psalm"],Composer 就会在 vendor/bin/ 里建两个指向实际脚本的符号链接——前提是这些脚本文件存在、有可执行权限、且第一行是有效的 shebang(比如 #!/usr/bin/env php)。
常见错误现象:vendor/bin/phpunit 报错 Permission denied,或直接提示 command not found。原因通常是:脚本没加 x 权限;shebang 写错(比如写成 #!/usr/bin/php 却没在系统路径下);或者脚本根本不在包根目录或 bin/ 子目录里。
- 脚本必须放在包内可被 Composer 找到的位置(通常为项目根目录或
bin/目录) - 运行
chmod +x bin/phpunit确保可执行位已设置 - shebang 必须是
#!/usr/bin/env php,不要硬编码 PHP 路径 - 发布包前用
composer install --no-dev && ls -l vendor/bin/验证链接是否生成成功
packagist.org 上的包为什么有的能进 vendor/bin,有的不能
不是所有包都会进 vendor/bin,关键看它的 composer.json 里有没有 bin 字段,以及字段值是否指向真实存在的可执行文件。比如 phpunit/phpunit 有 "bin": ["phpunit"],而 monolog/monolog 没有,所以前者装完就有 vendor/bin/phpunit,后者没有。
容易踩的坑:有些包把命令行工具放在 scripts/ 或 src/Console/ 下,但没在 bin 字段声明——这时它永远不会出现在 vendor/bin/;还有的包写了 "bin": ["bin/mytool"],但实际文件叫 bin/mytool.php,Composer 不会自动补扩展名,链接会失效。
-
bin字段值是精确路径,不支持 glob、不自动加.php - 私有包也适用,只要本地
composer.json里定义了bin,composer install就会处理 - 如果多个包声明了同名 bin(如都叫
foo),后安装的会覆盖先安装的链接——没有冲突警告
想让自己的 CLI 工具被别人通过 bin 调用,要满足哪些条件
你的工具要被别人 composer require 后自动进 vendor/bin/,光写 bin 字段不够,还得确保三件事:脚本能独立运行、入口清晰、路径正确。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
典型结构是:项目根目录下放一个 mytool 文件(无扩展名),开头是 #!/usr/bin/env php,接着是 <?php ,然后 require 自动加载器并调用主逻辑。别用 mytool.php,因为 Composer 不会帮你去掉扩展名去建链接。
- 脚本第一行必须是 shebang,且必须以
<?php开头(不能空行、不能注释) - 脚本中应使用
require __DIR__ . '/vendor/autoload.php';或相对路径加载依赖 - 在
composer.json中声明:"bin": ["mytool"],不是["mytool.php"] - 发布前跑一次
composer install && vendor/bin/mytool --version真实验证
vendor/bin 下的命令执行慢,或者报 autoload 错误
这不是 bin 字段的问题,而是脚本内部加载 autoloader 的方式不对。很多脚本直接写 require 'vendor/autoload.php',但这是相对当前工作目录的路径——如果你在子目录下运行 vendor/bin/mytool,就会找不到 vendor/autoload.php。
正确做法是用 __DIR__ 回溯到脚本所在位置,再向上找 vendor/autoload.php。否则每次执行都要触发 Composer 的 fallback 加载机制,既慢又容易失败。
- 错误写法:
require 'vendor/autoload.php'; - 正确写法:
require __DIR__.'/../vendor/autoload.php'; - 更健壮写法(兼容 phar 和非 phar 场景):
if (file_exists($a = __DIR__.'/../vendor/autoload.php')) { require $a; } - 如果用了
composer create-project,注意vendor/bin链接指向的是全局 vendor,不是项目 vendor
最常被忽略的一点:bin 脚本的执行路径和你当前 shell 的 pwd 无关,但它的 __DIR__ 是确定的——永远是 vendor/bin/ 下那个符号链接所指向的真实脚本位置。所有路径计算必须从那里出发,而不是假设自己在项目根目录。










