PSR-4自动加载规范是PHP-FIG制定的类自动加载标准,通过命名空间前缀与文件路径映射实现按需加载,要求前缀以反斜杠结尾并映射基目录,类名剩余部分转斜杠加.php构成路径,仅字符串替换、不扫描目录,相比废弃的PSR-0更简洁高效。

src 目录必须存在且是 PSR-4 自动加载的唯一源
Composer 扩展包不是随便放个 index.php 就能用的,src 是行业事实标准目录名,几乎所有工具链(包括 Laravel、Symfony、PHPStan、Psalm)都默认它为代码入口。你不叫 src,就得在 composer.json 里手动改 psr-4 映射,后续 CI/CD、IDE 支持、静态分析都会掉链子。
常见错误现象:Class not found 即使类文件真实存在,只因自动加载没命中路径;或 phpunit 找不到测试类,因为 autoload-dev 默认也指向 src。
-
src/下必须有至少一个命名空间根目录,比如AexPackagetest,且与composer.json中psr-4声明完全一致(大小写敏感) - 不要把服务提供者(如
PackagetestServiceProvider.php)放在app/Providers或根目录下——它属于包自身,必须进src/ - 如果包含命令行功能,命令类也应放在
src/Command/,而非bin/——bin/是给可执行脚本用的(如vendor/bin/mytool),不是代码存放地
composer.json 的 name 字段决定 require 时怎么写
这个字段不是“起个名字”而已,它是 Composer 解析依赖的唯一标识符。一旦写成 "aex/packagetest-for-laravel",你在主项目里 require 时就必须写 "aex/packagetest-for-laravel": "dev-main",拼错一个字母、大小写不一致、多加个 -for-laravel 后缀,composer require 就直接报 Could not find package。
使用场景:本地开发阶段常配合 path 仓库,此时 name 还要和主项目 repositories 配置里的 url 路径下实际存在的 composer.json 内容严格对齐。
- 命名格式必须是
vendor/name,全部小写,用短横线-分隔单词(如linxi/exception-helper),不用下划线或驼峰 - 不要为了“语义清晰”加版本号或环境词(如
my-pkg-laravel-10),这会让升级和跨框架复用变得脆弱 - 如果你打算发布到 Packagist,
vendor名建议用 GitHub 用户名或组织名,避免未来重名冲突
tests 和 bin 目录要不要?什么时候加
tests 不是可选装饰,而是包可维护性的底线。没有测试,别人不敢 require 你的包,你自己也不敢重构。而 bin 只在包本身提供 CLI 工具时才需要,95% 的 Laravel 扩展包根本用不上。
性能影响:空的 tests/ 目录不会拖慢 composer install,但缺少它会让 composer test(或自定义 script)直接失败;bin/ 如果存在却没配置 bin-compat 或正确 bin 字段,Composer 会警告甚至跳过安装。
-
tests/应与src/平级,结构镜像(如tests/Aex/Packagetest/对应src/Aex/Packagetest/) - 在
composer.json中声明"autoload-dev": {"psr-4": {"Aex\Packagetest\Tests\": "tests/"}},否则 PHPUnit 加载不到 -
bin/仅当你的包导出可执行命令(如mytool)时才建,且必须在composer.json中写明"bin": ["bin/mytool"],否则不会软链接进vendor/bin/
为什么不能把包直接丢进 Laravel 的 packages/ 目录就完事
因为 Laravel 不认识 packages/ —— 它只是你个人约定的临时工作区。真正起作用的是两件事:主项目的 composer.json 是否通过 repositories 声明了该路径,以及该路径下的包是否自带合法 composer.json。缺一不可。
容易踩的坑:有人把包放 packages/aex/packagetest,却忘了在主项目 composer.json 的 repositories 里加对应条目,结果 composer require aex/packagetest-for-laravel 永远失败;或者加了,但 url 写成绝对路径("C:/work/packages/aex/packagetest"),在 CI 或队友机器上静默失效。
- 路径必须用相对写法,例如
"../packages/aex/packagetest"(从主项目composer.json所在位置出发) - 本地包目录下必须已有
composer.json,且已执行过git init && git add . && git commit -m "init"—— Composer 2.2+ 会跳过未初始化 Git 的 path 目录 - 不要在本地包自己的
composer.json里写repositories,那对主项目毫无意义
真正的复杂点不在目录名本身,而在每个目录背后绑定的工具链契约:PSR-4 加载规则、Composer 元数据解析逻辑、Git 初始化状态、路径解析层级。少对齐一处,Class not found 或 Could not find package 就立刻出现。











