十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PHP依赖管理工具Composer从安装到实战:解锁自动化依赖与自动加载

PHP依赖管理工具Composer从安装到实战:解锁自动化依赖与自动加载 1. 为什么 PHP 开发绕不开 ComposerComposer 是 PHP 的依赖管理工具也是 PHP 生态里绕不开的基础设施。你可以在自己的脚本里手动 require 一堆文件也可以靠 git clone 拉来各种第三方库但只要项目规模稍微涨一点你就会体会到什么叫“依赖地狱”A 需要 B 1.xC 需要 B 2.x你手动解开一个另一个又塌了。Composer 干的事就是把整套依赖解析、版本匹配、自动加载、锁定环境这些脏活统统接过去。我见过太多刚转 PHP 的开发者拿着 Laravel 或 ThinkPHP 的源码直接 PHP 一跑报错一堆 vendor 目录缺失然后一脸懵。原因很简单没用 Composer 安装依赖。无论你是做 Web 接口、写 CLI 脚本、搞单元测试还是维护一个五年历史的老项目Composer 都是第一步。装好它你才真正进入现代 PHP 开发的节奏。前面提到的这个“依赖管理”能力是 Composer 生存的根基。它本质上是一个包管理器对标 Node.js 的 npm、Python 的 pip、Ruby 的 bundler。它从 Packagist 仓库拉取包根据每个包的 composer.json 里声明的版本约束算出当前项目能用的最合理组合然后下载到 vendor 目录再生成一个自动加载脚本让你能用 use 语句优雅地调用第三方类。它还能生成 composer.lock 文件把每个包的具体版本和下载哈希冻结下来保证团队开发和生产环境装的是同一份代码。1.1 Composer 解决的核心问题从手工搬运到自动解析没有 Composer 的年代PHP 开发者往项目里加一个第三方库的流程是这样的去官网下载 zip解压到 lib 目录手动 require 文件再祈祷这个库没有依赖其他库。如果它依赖了另一个库你就得递归地重复这个过程。我当时维护一个老项目光日志库就带了三个版本因为不同的模块各引一套谁都不敢删删了某个按钮可能就崩了。Composer 把这个过程压缩成了两个命令composer require monolog/monolog composer install它会读取项目里的 composer.json解析你声明的依赖以及这些依赖自身的依赖自动计算出合适的版本集合下载到 vendor 目录并生成一个 autoload.php。你只需要在入口文件写一行 require vendor/autoload.php接着想用什么类直接 use 就行。这套机制把 PHP 从“手动 include/require 地狱”里彻底解放出来。1.2 Composer 与 npm/pip 的定位对照很多开发者刚上手时容易把 Composer 理解成“PHP 版的 npm”这个类比大方向没错但有几个差异需要提前心里有数对比项Composernpmpip锁文件composer.lockpackage-lock.json无标准推荐 pip-tools安装位置vendor 目录随项目走node_modulessite-packages全局/虚拟环境全局依赖不推荐可全局默认全局自动加载PSR-4/PSR-0/Classmap 自动生成CommonJS/ESM显式 importComposer 和 npm 最大的不同是 Composer 强烈推荐“每个项目一个 vendor 目录”不搞全局安装那一套。Laravel 也好你自己的小工具也罢依赖都锁在项目内部。这样做的好处是版本隔离坏处是磁盘会多占用一点但对 PHP 项目来说这点成本完全可以接受。2. 安装前的环境准备先把地基打牢在敲下安装命令之前我强烈建议你先花 5 分钟确认自己的 PHP 环境。很多安装失败的案例不是命令敲错了而是 PHP 版本太低、扩展缺失、或者内存限制太小。Composer 本身是有最低版本要求的你用太老的 PHP 去跑它它自己先罢工。2.1 PHP 版本怎么选Composer 2.x 官方推荐 PHP 7.2.5 以上我实测下来PHP 7.4 和 PHP 8.x 都是非常顺滑的。如果你用的是 PHP 5.6 甚至更老的版本建议先升级 PHP 本身不要指望在旧版本上硬跑新版 Composer。原因有两个一是 Composer 自身用到了不少新语法老版本 PHP 跑不动二是 Packagist 上大量包已经逐步放弃老版本支持你装完 Composer 也拉不到合适的依赖。判断 PHP 版本的命令很直接php -v如果输出里能看到 PHP 8.2.x 之类的字样环境基本没问题。如果看到 5.x先停一停装 Composer 之前得把 PHP 升级了。Windows 用户我建议直接装一个集成环境Linux/macOS 用户则根据包管理器来装对应版本。2.2 必须确认的 PHP 扩展与配置项Composer 运行时会用到一批 PHP 扩展包括常用的 JSON、OpenSSL、PDO、Mbstring、Tokenizer、Ctype 等。大部分场景下这些扩展是默认开启的但如果你用的是精简版 PHP 或自己编译的 PHP很容易缺扩展。推荐装完 PHP 后跑一下php -m输出里能看到模块列表。如果缺了 JSON 或 OpenSSLComposer 基本跑不起来。另一个关键点是 PHP 的 memory_limit默认 128M 在解析大型依赖树时可能会报内存不足。我一般建议至少在 CLI 阶段放宽到 512Mphp -d memory_limit-1 composer.phar install这个可以临时覆盖不必改全局配置文件后面我会在常见问题部分再详细展开。2.3 Windows / Linux / macOS 环境差异Windows 用户最省事的方式是下载 Composer-Setup.exe 安装包它会自动帮你把 PHP 路径找出来同时安装一个 composer.bat直接在命令行敲 composer 就能用。Linux 和 macOS 则比较喜欢手动下载 composer.phar 并移动到 /usr/local/bin。macOS 上如果装了 Homebrew直接 brew install composer 也行唯一要注意的是 Homebrew 仓库里版本可能稍微落后装完可以手动升级。Docker 用户其实是最省心的直接用官方镜像docker run --rm -v $(pwd):/app composer:2 install也不需要在本机装 PHP一个容器全搞定。后面我会单独讲。3. 主流安装方式实测对比Composer 的安装方式花样很多但说白了就三种官方脚本、包管理器、Windows 安装器。我建议你把每种方式都了解一遍因为不同环境用得上。3.1 Linux/macOS 用官方脚本安装这是最通用也最“原始”的方法。流程是下载官方安装器脚本然后执行它生成 composer.pharphp -r copy(https://getcomposer.org/installer, composer-setup.php); php composer-setup.php php -r unlink(composer-setup.php);执行完会产生一个 composer.phar 文件。phar 就是 PHP Archive本质是一个可执行的压缩包。你可以直接用php composer.phar来调用也可以把它挪到系统 PATH 里这样就不用每次带上 phpsudo mv composer.phar /usr/local/bin/composer composer --version为什么这里用 copy 而不是直接 curl官方文档其实两种方式都写了我习惯用 PHP 的方式因为它能自动带上 PHP 环境里配置的 SSL 证书遇到证书问题出错率更低。如果你用 curl 的方式碰到 HTTP 代理或证书问题会多一些排查步骤。3.2 官方安装器脚本的隐藏坑你有没有遇到过这样的情况直接 curl 管道执行官方安装器装到一半提示 openssl 扩展版本不匹配我踩过好几次。原因是你系统的 PHP 和 curl 用的 SSL 库可能不是同一套。更稳妥的做法是先把安装器下载到本地然后校验一下哈希再执行wget https://getcomposer.org/download/latest-stable/composer.phar php composer.phar --version下载地址里 latest-stable 表示最新稳定版。这种方式不经过安装器直接拿到 composer.phar省去中间环节。我后来维护服务器基本都是这么装的因为它幂等性好重复执行不会出幺蛾子。3.3 Windows 安装器与手动方案Windows 用户我推荐直接去官网下载 Composer-Setup.exe。它会在安装过程中检测你的 PHP 可执行文件位置选择 php.exe 后一路下一步就行。最终会生成 composer.bat并添加到系统 PATH 中你在 cmd 或 PowerShell 里直接敲 composer 就能用。有个细节需要注意如果你用的是 phpstudy、小皮面板这类集成环境PHP 版本可能不止一个。安装器识别到的是环境变量里配置的那个 PHP如果你在集成环境里切换了版本Composer 还是会使用旧的路径。建议安装前先确认系统的 PHP 版本到底指向哪里where php这个命令会列出所有 php.exe 的路径。如果发现 Composer 对应的 PHP 不是你想用的那个直接修改环境变量 PATH 的优先级即可。3.4 Homebrew 与 apt 包管理器装 ComposermacOS 用 Homebrew 是最省事的brew install composerLinux 上不同发行版也有对应的包# Debian/Ubuntu sudo apt install composer # CentOS/RHEL sudo dnf install composer用包管理器安装的好处是省心自动解决依赖。但坏处也明显版本经常滞后。比如你 apt 装出来的可能是 2.5.x而官方已经出了 2.7.x。好在你还可以用 Composer 自己更新自己composer self-update如果在共享主机上没有 sudo 权限就用最开始的 phar 方案把 composer.phar 放到自己用户目录下面的 bin 目录再手动改 ~/.bashrc 加 PATH。3.5 我最终推荐的安装路径如果你问我现在新环境怎么装我会说本地开发机优先用包管理器图省心生产服务器用官方 composer.phar 手动放到 /usr/local/bin版本完全可控Docker 环境用官方镜像。这样每个场景都能找到最顺手的方式。4. 安装后的第一步全局配置与镜像加速装完 Composer 不代表万事大吉。Composer 默认从 Packagist 官方仓库下载包由于网络环境因素访问官方仓库时下载速度和质量经常不稳定。这不是 Composer 本身的问题而是国际网络链路的问题。所以安装完的第一件事我建议先把全局镜像源切到国内可用的镜像节点让依赖下载快得飞起。4.1 全局镜像源配置以腾讯云镜像为例一条命令搞定composer config -g repo.packagist composer https://mirrors.cloud.tencent.com/composer/阿里云也有类似镜像composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/-g表示写进全局配置这样所有项目都会继承这个镜像源。配置后你可以执行以下命令验证composer config -g --list在输出里能看到 repo.packagist 变成你设置的镜像地址。镜像源会把 Packagist 仓库的数据周期性同步到国内节点你下载依赖时走的是国内节点的 CDN速度提升非常明显。这个配置对安装速度和成功率的影响是立竿见影的很多人在这一步就绕开了后续大半的网络问题。4.2 全局参数与 allow-pluginsComposer 2.2 开始引入一个交互式确认机制当一个包声明了插件时会询问你是否允许执行。如果不允许插件相关的功能就不会执行。这个机制本意是安全考虑但对新手来说经常造成困惑“我装了个包怎么自动加载失效了”常见的是安装 laravel 相关包时会弹出提示 require allow-plugins。你可以提前在全局配置里写明允许哪些插件避免安装时的交互等待。比如这样写composer config -g --unset plugin-api-version composer config -g allow-plugins.composer/installers true composer config -g allow-plugins, true第二条命令里的allow-plugins, true会允许所有插件。这是省事但从安全角度有点放飞自我如果项目里全是可信来源的包可以这么干如果拉了很多第三方包建议精确到具体插件名。4.3 缓存目录与超时设置Composer 会把下载过的包缓存到本地默认在 ~/.cache/composerLinux或 ~/AppData/Local/ComposerWindows。如果你磁盘空间紧张可以设置缓存目录composer config -g cache-dir /data/composer-cache网络不好时Composer 默认 300 秒超时可能不够用。我见过依赖树庞大的项目解析阶段就跑了十几分钟。可以把超时调大composer config -g process-timeout 2000这里单位是秒2000 秒足够应对绝大多数场景。改了这两个参数之后安装大型框架时会明显感到不容易在中间断了。5. 拿起 Composer从项目初始化到生产部署Composer 装好、配置好这只是热身。下面我带你过一遍最日常的工作流初始化项目、安装依赖、理解 lock 文件、使用自动加载。这套流程是 PHP 项目开发的地基掌握了它后面用框架也好自己搭项目也好都顺畅很多。5.1 composer init 创建项目进入项目目录后执行composer init它会交互式问你包名、描述、作者、依赖等信息。不想回答那么多问题也可以直接全部默认然后后续改文件。生成的 composer.json 大致长这样{ name: yourname/demo, description: A demo project, require: { php: 7.4, monolog/monolog: ^2.0 }, autoload: { psr-4: { App\\: src/ } } }字段不复杂name 是包名require 是依赖清单autoload 告诉 Composer 怎么加载你自己的类。很多新手在这个阶段会直接手写 composer.json我不推荐因为手写容易漏掉 JSON 格式错误或 autoload 配置错误。用 composer init 生成再去改出错的概率低得多。5.2 composer install 与 composer update 到底差在哪这是 Composer 使用中最容易混淆的一对命令。composer install 根据 composer.lock 文件安装固定版本。composer update 根据 composer.json 的版本约束重新解析并更新依赖。听起来简单但实际项目里很多人因为搞混这两条命令吃了大亏。我举一个真实案例一位同事在改需求时执行了 composer update结果框架从一个次版本跳到了另一个次版本接口签名变了线上直接 500。后来我们约定一条铁律本地能顺利运行的前提下绝不在生产环境执行 composer update。composer.lock 文件会把每一个包的具体版本、下载地址、哈希值全部锁住。这个文件一定要提交到 Git 仓库里。这样做的好处是团队其他成员 clone 代码后执行 composer install 就能得到与你完全一致的环境谁也不会因为依赖版本不同而出现“本地能跑部署就不行”的尴尬。5.3 生产环境安装依赖要加 --no-dev开发时要装 PHPUnit、Mockery 这类测试工具但生产环境完全用不上。composer.json 里会把这类依赖写在 require-dev 里生产环境安装时跳过composer install --no-dev --optimize-autoloader--no-dev 表示不安装 require-dev 中的包--optimize-autoloader 会把 PSR-4 和 PSR-0 规则转换成 classmap加快加载速度。这个习惯能帮你在生产服务器少装几十个无用的包降低出问题概率也加快部署速度。5.4 composer.lock 提交还是不提交我的答案非常明确提交。不管你是做开源库还是闭源项目lock 文件都建议放入版本库。唯一例外是你在开发一个通用工具库希望用户安装时能解析到最新兼容版本那可以不提交。但绝大多数业务项目场景提交 lock 文件能带来环境一致性带来的好处远大于那一点“自动更新”的便利。5.5 autoload 自动加载机制解析执行完 install 后Composer 会生成 vendor/autoload.php。你自己的代码里加这一行就能自动加载所有第三方包require __DIR__ . /vendor/autoload.php;而你自己的类可以通过 composer.json 里的 autoload.psr-4 配置来加载。我习惯把所有业务类放在 src/ 目录下命名空间是 App那么类文件路径和命名空间就形成一一对应关系App\Http\Controllers\UserController 对应 src/Http/Controllers/UserController.php。当你新增了类文件默认情况下 autoload 是实时找文件的不需要重新生成但如果用到了 classmap 或者新增了命名空间规则需要执行composer dump-autoload这个命令会重新扫描自动加载规则生成最新的 autoload 文件。在部署脚本里我通常会先执行 composer install --no-dev --optimize-autoloader然后执行 composer dump-autoload -o确保类映射是最优状态。6. 实战问题排查与避坑技巧无论你多熟练Composer 安装和依赖处理过程中总会碰到各种意想不到的问题。这里我挑几个出现频率最高、也最有代表性的结合我自己排障的现场记录说一说。6.1 内存不足PHP Fatal error: Allowed memory size这是安装大项目时最经典的问题。Composer 在解析依赖时会把大量包元数据读入内存默认 128M 很容易被爆掉。解决办法是在执行命令时临时抬高内存限制php -d memory_limit-1 composer.phar install如果用的是全局 composer 命令也有一套等价写法COMPOSER_MEMORY_LIMIT-1 composer install这个环境变量会被 Composer 自动读取实测很有效。长期方案还是修改 php.ini 里的 memory_limit把 CLI 环境的上限调到 1G 以上。注意改之前看下是哪个 php.ini 生效命令行用的和 Web 用的可能不是同一个。6.2 网络超时与下载失败“Failed to download XXX from dist” 这类报错百分之八十是网络问题。第一选择是检查镜像源是否配置正确。如果你已经按第 4 节配置了国内镜像还是不时超时可以把策略改成优先下载源码包而不是压缩包composer config -g preferred-install source这个配置会让 Composer 优先从 git 仓库拉取源码而不是从 dist 压缩包下载。代价是下载体积更大、耗时更长但遇到 CDN 抽风时源码方式往往能正常拉下来。还有一种场景是公司内网有私有依赖库需要在 composer.json 里配置 repositories 指向内网地址这里就不展开了。6.3 缺少 PHP 扩展的提示有时你满心期待地执行 composer install结果爆出Package xxx/yyy requires ext-curl but it is not present.这说明当前 PHP 环境缺少对应扩展。缺什么就装什么Windows 用户建议直接改 php.ini去掉 extensioncurl 前面的分号Linux/macOS 用户看发行版# Ubuntu sudo apt install php8.2-curl # CentOS sudo dnf install php-curl装完扩展记得重启 PHP-FPM 或重新登录 Shell否则 CLI 里可能依然检查不到。确认扩展是否生效php -m | grep curl6.4 依赖冲突composer why 和 why-not 的妙用“Your requirements could not be resolved to an installable set of packages” 这种报错新手看完一脸懵老手也会头疼。它表示当前依赖组合里产生了版本冲突。排查思路是先定位是谁在冲突用这两个命令composer why another/package composer why-not php 8.0why 会展示为什么这个包被引入以及是谁依赖了它why-not 会告诉你某个包为什么不能兼容某个版本。这两个命令能帮你快速画出依赖关系链。我处理冲突的经验是除非业务必须否则不轻易降低主框架的版本要求优先考虑升级冲突链路上的某个依赖或者使用 composer update 来重新解析全部依赖。6.5 常见问题速查表症状原因处理方式PHP Fatal error: Allowed memory size内存限制太低php -d memory_limit-1 或 COMPOSER_MEMORY_LIMIT-1Failed to download...网络无法访问 dist 地址配置国内镜像源或切换 preferred-install sourceproc_open(): fork failedPHP 函数被禁用在 php.ini 的 disable_functions 中移除 proc_open并重启 PHPClass not foundautoload 规则未生效composer dump-autoload -o检查 composer.json 的 psr-4 路径Your requirements could not be resolved版本冲突composer why 定位冲突链调整 composer.json 版本约束Composer 版本过旧无法安装新版包composer self-updateallow-plugins 交互提问卡住插件确认机制全局配置 allow-plugins或精确允许对应插件6.6 Composer 自身升级Composer 的升级本身就是一条命令composer self-update如果你是通过 phar 安装的这条命令会直接替换 composer.phar。如果你是 brew 或 apt 安装的self-update 可能没有权限覆盖系统目录这时可以用包管理器升级# Homebrew brew upgrade composer # apt sudo apt update sudo apt upgrade composer升级之后记得跑一下composer diagnose它会检查环境配置、网络链路、镜像源等一堆项目。如果输出里全部显示 OK那说明你的 Composer 环境非常健康。7. 一个有趣又硬核的玩法用 Composer 驱动 bytebeat composer聊到这里Composer 安装和基础使用已经讲得差不多了。最后分享一个我最近研究的小项目正好能把 Composer 的用处延伸到音乐创作场景。最近“bytebeat composer”这个小众概念在程序员圈子里火了一把它说的不是 PHP 的 Composer而是用一行数学公式实时生成芯片音乐的演奏/作曲方式通常通过代码循环快速输出音频样本。我第一次看到 bytebeat 相关作品时第一反应是这不就是用代码“写音乐”吗后来深入研究了一下发现它的核心逻辑特别简单在音频采样循环里不断执行一个整数算式生成 8bit 格式的采样值这些值连续播放出来就形成了一首复古电子乐或者至少是很有味道的噪音音乐。它不需要任何音频素材只要一个能算出数字的循环加上能把数字变成声音的播放器。7.1 bytebeat composer 到底是个什么东西简单说bytebeat 是一种算法音乐创作方式。经典代表就是一段类似这样的公式t t 8其中 t 表示采样序号从 0 开始一个循环推进一次。它用几个位运算就构造出节奏和音高变化效果出奇地丰富。把它想成“代码即乐谱”可能更贴切音符不是写在五线谱上而是藏在计算公式里。而 bytebeat composer 这个短语指的是基于这种算法做旋律/音色编排的工具或方案。有些项目是 Web 端在线编辑器直接给你一个文本框你输入公式浏览器就立刻播放声音有些则是把 bytebeat 和固定曲式结合做成一个小作曲环境。对搞音乐又写代码的人来说这类项目是玩具也是技术甜点。7.2 我用 PHP Composer 实现了一个最小版既然 Composer 本来就是个包管理工具我决定动手试试能不能在 PHP 环境下用 Composer 搭建一个 bytebeat 生成器。思路很简单先建一个项目用 Composer 初始化然后不依赖任何第三方包纯手写一段循环生成 WAV 文件。这既能验证 Composer 项目结构也能跑通 bytebeat 的完整流程。先初始化项目mkdir bytebeat-php cd bytebeat-php composer init --namemy/bytebeat --no-interaction创建的 composer.json 里只有一个基本结构。接着我写一个 src/Bytebeat.php封装一个最简单的生成函数?php namespace My\Bytebeat; class Bytebeat { public function render(int $sampleRate 8000, float $duration 4.0): string { $count (int) ($sampleRate * $duration); $pcm ; for ($t 0; $t $count; $t) { $value (($t * 3) ($t 5)) 0xff; $pcm . chr($value); } return $this-toWav($pcm, $sampleRate); } private function toWav(string $pcm, int $sampleRate): string { $dataLen strlen($pcm); $header RIFF . pack(V, 36 $dataLen) . WAVE; $header . fmt . pack(V, 16) . pack(v, 1) . pack(v, 1); $header . pack(V, $sampleRate) . pack(V, $sampleRate) . pack(v, 1) . pack(v, 8); $header . data . pack(V, $dataLen); return $header . $pcm; } }这里的公式($t * 3) ($t 5)就是一个非常经典的 bytebeat 表达式。它把 t 乘 3 之后做位与运算再右移 5 位。结果会随着 t 的增长变化出非线性的节奏和音高。每次得到 0~255 的整数转换为一个字节就是 8bit 采样值。8kHz 采样率、4 秒时长最后封装成标准 WAV 文件。然后在 bin/render.php 里调用?php require __DIR__ . /../vendor/autoload.php; use My\Bytebeat\Bytebeat; $output $argv[1] ?? output.wav; file_put_contents($output, (new Bytebeat())-render()); echo Generated: {$output}\n;执行一下composer dump-autoload php bin/render.php bytebeat.wav如果一切正常项目目录下会多出一个 bytebeat.wav用任意播放器打开就能听到一段“科技感”十足的循环音轨。整个实现过程只用到了 Composer 的自动加载机制没有引用任何第三方库却能验证 Composer 项目从初始化、命名空间、autoload 到实际运行的完整链路。7.3 这个玩法的意义与扩展方向用 Composer 写 bytebeat 生成器本质上是“依赖管理工具”和“算法音乐”的跨界结合。它说明 Composer 不仅是装 Laravel 或装 PHPUnit 的工具它也是一个可以让尝试新点子变得很轻松的起点。你想做实验性项目执行 composer init 就能搭好脚手架再借助 PSR-4 自动加载把代码组织得干净整洁随时可以复现。如果你对 bytebeat 有兴趣可以在 Composer 项目里继续扩展加入命令行参数控制公式支持直接输出 PCM 流式播放甚至接入 WebSocket 做成实时编曲。有心的朋友还可以去 Packagist 上搜 “bytebeat” 相关包很多现成实现可以拉下来对比学习不过我先提醒一句那些包的维护状态参差不齐直接用之前还是看一下源码和兼容性更稳妥。8. 最后再分享两个安装与使用阶段的个人心得第一个心得是装完 Composer 之后第一件事不是立刻跑 composer install而是先跑 composer diagnose。这句话我重复了很多遍因为我踩过太多“明明照着教程装好了怎么还是报错”的坑。diagnose 会把 PHP 版本、扩展、路径、镜像、缓存、git 配置等问题一次性扫描出来省得自己一个一个查。第二个心得是关于版本管理的永远不要把 composer update 当作顺手操作。我自己经历过一次线上故障起因就是有人为了装一个新包在服务器上执行了 composer update结果十几个间接依赖被升级框架内部接口行为变化导致线上接口大面积 502。从那以后我要求团队所有依赖变更都在本地完成更新验证后再提交 composer.json 与 composer.lock生产环境只执行 composer install。这个习惯帮我们少出很多乱子。Composer 的安装真的只是最浅的一步后面依赖策略、镜像配置、lock 文件管理、自动加载优化才是真正决定项目稳定性与协作效率的地方。希望这篇文章能帮你把 Composer 这块地基打稳。
返回列表