如何配置Composer实现本地开发软链+部署干净安装?
我本地维护着一个PHP网站项目,同时自己写了个微型Web框架,想把它做成Composer包给这个网站用。核心需求是两者并行开发但完全独立,而且部署网站的时候,得像安装Guzzle这种常规第三方包一样,正常安装这个框架。
目前我已经配置好了两个项目的composer.json:
网站项目的配置:
{ "repositories": [ { "type": "path", "url": "/local/path/to/framework/package", "options": { "symlink": true } } ], "require": { "my/framework": "dev-master", "guzzlehttp/guzzle": "6.3.3" } }
框架包的配置:
{ "name": "my/framework", "description": "A tiny framework.", "autoload": { "psr-4": { "MyFramework\\": "src" } } }
现在遇到了两难的问题:
- 本地开发时,执行
php composer.phar update会创建软链,框架代码改完立刻同步到网站,开发体验贼好; - 但部署的时候就麻烦了:部署脚本会导出网站Git分支的归档,传到服务器后执行
php composer.phar install,这时候软链直接失效;如果把symlink选项去掉,开发时每次改框架都得跑update,太繁琐,而且部署时也只会复制dev-master分支的代码; - 试过把仓库类型改成
vcs,但Composer会克隆整个框架仓库,不管是本地开发还是部署,完全没必要。
想请教两个问题:
- 有没有办法不用修改现有的composer.json,就能让Composer同时满足「本地开发软链实时更新」和「部署时安装干净框架包」的需求?
- 如果要给框架打正式版本标签,最优的流程是什么?
一、无需修改composer.json的兼容方案
其实完全不用改配置文件,靠Composer自带的参数就能搞定这个矛盾,我给你拆解两种场景:
本地开发模式(保留软链,实时同步)
平时开发的时候该咋用咋用——你现有的配置已经完美适配本地开发了:symlink: true的path仓库会自动创建软链,框架代码改完网站这边立刻就能用,根本不用跑composer update,爽得很。
部署模式(安装干净代码,避免软链失效)
部署的时候,只需要在执行composer install的时候加一个参数,就能强制Composer复制代码而不是创建软链:
php composer.phar install --no-symlinks --no-dev --optimize-autoloader
给你解释下这几个参数的作用:
--no-symlinks:不管composer.json里有没有配置symlink: true,Composer都会直接复制框架的代码到vendor目录,彻底解决软链在部署后失效的问题;--no-dev:只安装生产环境需要的依赖,跳过开发依赖(如果你的项目有的话);--optimize-autoloader:优化自动加载器的性能,适合生产环境。
就这么简单,本地开发正常执行composer install/update,部署时加个--no-symlinks参数,完全不用动现有的composer.json。
如果这个方法不够灵活,还有个备选方案:部署时用环境变量临时覆盖仓库的symlink配置,不过相比上面的参数,这个稍显复杂,一般用不上:
COMPOSER_REPOSITORIES='[{"type": "path", "url": "/local/path/to/framework/package", "options": {"symlink": false}}]' php composer.phar install --no-dev --optimize-autoloader
二、给框架打正式版本标签的最优方案
当框架稳定后,打正式版本的流程建议遵循下面的步骤,既规范又能兼容本地开发和部署:
遵循语义化版本规范(SemVer)
版本号按主版本号.次版本号.修订号来命名,比如1.0.0、1.1.0、1.0.1:- 主版本号:当你做了不兼容的API修改时升级;
- 次版本号:新增了向后兼容的功能时升级;
- 修订号:只做了向后兼容的bug修复时升级。
在框架仓库打Git标签
切换到框架仓库的稳定分支(比如master),执行下面的命令打标签并推送到远程仓库:git tag -a v1.0.0 -m "Release version 1.0.0" git push origin v1.0.0标签名加
v前缀是PHP生态的常见惯例,看着更清晰。更新网站项目的依赖配置
把网站composer.json里的"my/framework": "dev-master"改成具体的版本范围,比如:"require": { "my/framework": "^1.0.0", "guzzlehttp/guzzle": "6.3.3" }用
^前缀表示允许Composer安装1.0.x、1.1.x等兼容的版本,这是语义化版本的最佳实践。可选:发布到Composer仓库
- 如果框架是公开的,直接提交到Packagist就行,这样网站项目里甚至可以去掉path仓库的配置,Composer会自动从Packagist拉取;
- 如果是私有框架,可以搭建私有Composer仓库(比如Satis、Toran Proxy),或者继续用path仓库——只要框架仓库是Git仓库,Composer会自动识别标签对应的版本,本地开发依然可以用软链,部署时用
--no-symlinks安装指定版本的干净代码。
本地开发与部署的兼容
打了正式版本后,本地开发时依然可以用path仓库的软链模式,Composer会优先使用本地的框架代码;部署时还是用--no-symlinks参数,就能安装指定版本的干净代码,完美兼容两种场景。
内容的提问来源于stack exchange,提问作者dirtside

