composer create-project更适合新建项目,因为它直接拉取完整可运行的框架骨架并自动安装依赖、生成自动加载文件及执行初始化脚本,而composer init仅生成空的composer.json,需手动配置依赖、autoload和Git等,新手易出错。

直接用 composer create-project 启动新项目,比 composer init + 手动装依赖快得多,也更少出错——尤其当你用的是 Laravel、ThinkPHP、Symfony 这类标准骨架时。
用 create-project 快速拉起可运行的项目骨架
这是最接近“开箱即用”的方式,create-project 不只是下载代码,它会自动执行 composer install、生成 vendor/autoload.php、甚至触发框架预设的脚本(比如生成 key、初始化配置)。
常见错误现象:手动 git clone 框架仓库后运行 composer install 失败,因为缺少 composer.lock 或平台扩展未声明。
- 正确做法是始终优先走
composer create-project vendor/name project-dir [version],例如:composer create-project topthink/think tp8 - 加
--prefer-dist参数能跳过源码克隆,直接下载压缩包,速度更快、网络更稳 - 如果项目依赖特定 PHP 版本或扩展(如
ext-pdo_mysql),create-project会在安装前校验,失败时明确提示,而init+require可能拖到运行时报错
init 适合什么场景:从空目录起步的库或轻量工具
composer init 的价值不在“新建应用”,而在定义一个可发布、可复用的包。它生成的 composer.json 是 Packagist 上所有 PHP 包的元数据基础。
立即学习“PHP免费学习笔记(深入)”;
使用场景:你要写一个通用的图片处理工具类、一个 CLI 小命令、或一个供其他项目 require 的私有组件。
- 交互式提问中,
type字段填library而非project,这会影响后续打包和安装行为 - 别跳过
autoload配置——哪怕只写一条"psr-4": {"MyLib\": "src/"},否则别人require你的包时类根本不会被加载 - 如果已有旧代码,不要强行塞进
src/再配 PSR-4;先用"files": ["helpers.php"]加载全局函数,再逐步迁移
require 和 install 的关键区别与误用点
composer require 改 composer.json 并立即装包;composer install 只读 composer.lock 安装——这是保证环境一致的核心机制,但很多人在 CI/CD 或部署时仍用错。
典型问题:本地开发用 require 装了新包,Git 提交漏了 composer.lock,线上 install 拉到的是旧版本或冲突版本。
- 应用项目必须提交
composer.lock,且 CI 流水线应严格用composer install --no-dev(生产环境不装 dev 依赖) -
composer require --dev phpunit/phpunit才会写进require-dev,直接require phpunit/phpunit会进require,导致生产环境也装测试框架 - 想临时试一个包又不想污染
composer.json?用composer global require,但仅限 CLI 工具类(如phpstan/phpstan),别用于项目依赖
autoload 配置写错的三个隐蔽坑
PSR-4 映射路径不对,vendor/autoload.php 就不会加载你的类——但错误往往不报致命异常,而是静默失败,直到你调用某个方法时才抛 Class not found。
最容易被忽略的是路径分隔符和命名空间末尾反斜杠。
-
"App\": "app/"✅ 正确:命名空间以双反斜杠结尾,路径是相对 vendor 目录的子目录 -
"App": "app/"❌ 错误:单反斜杠在 JSON 中会被转义,实际变成"App"(无尾部反斜杠),导致自动加载器无法匹配 -
"App\": "./app/"❌ 错误:.在 autoload 路径中无效,Composer 只认相对于项目根目录的路径,不支持相对定位符 - 改完
autoload后必须运行composer dump-autoload,否则变更不生效;加-o参数可生成优化后的类映射,提升加载速度
真正卡住人的从来不是命令记不住,而是 composer.json 里一行路径写错、一个反斜杠少打、或者 composer.lock 没提交——这些细节在本地可能一切正常,一上服务器就崩。



















