composer作为php领域最为流行的包依赖管理器,基本也成为每个phper的必备技能之一,composer官方也提供了很好的中文学习资料,整体而言也是很容易上手的。自己在使用composer的过程中也遇到了概念不清晰和实践方面的问题,所以用这篇文章来记录总结一下。
问题1:该不该将vendor文件夹包裹在源代码管理器(git、svn等)中?
vendor文件夹通常都会比较大,不将其放在源代码管理器中,可以减少仓库的体积和历史提交差异记录,加快代码签入签出的速度,所以一般不将vendor包放在仓库中。但是需要注意一些问题,因为有时候composer安装的过程中需要执行一些检验token的操作,在持续集成的工具中要预留一些解决方案。
问题2:composer提供了install和update命令来维护vendor包,那么这两个命令有什么区别呢?
与composer明确相关的有三个东西:composer.json文件、composer.lock文件和vendor文件夹。后两者都由composer自行管理,所以与开发者密切相关的就是composer.json文件。
要回答这个问题,前提就是要区分应用场景。假如一个项目之前完全没用过composer,现在刚刚创建好了composer.json文件,那么用install和update命令都可以完成同样的工作:生成包源文件集合vendor和composer.lock锁文件。两个命名之间没有本质区别。
假如项目已经使用了composer,现在修改了composer.json文件,想修改包的版本或者增加第三方包的引入,那么必须使用update命令,因为install命令会根据composer.lock来生成包源文件,它是不会去识别composer.json的改动的。
上述的场景中,用update命令就可以满足了,那么install命令应该在什么场景下使用呢?答案就是在生产环境中。我们可以在开发环境中维护好composer.lock文件,并将.lock文件提交到代码仓库中,到了生产环境就只用install命令,根据.lock文件生成vendor包,就不会造成生产环境贸然更新了某个包与开发环境不一致的问题。
问题3:composer的包版本号提供了多种约定方式,那么在项目中最好用哪种方式呢?
composer官网明确介绍了包的约定方式:
- 确切的版本号: 1.0.2
- 范围: >=1.0 大于1.0的版本
- 通配符: 1.0.* 1.0下的子版本
- 赋值运算符: ~1.2 相当于范围>=1.2,<2.0
我们最常用的使用场景应该是在require下面包裹一个第三方组件进来,这时候我认为最好的方式是使用明确版本号的方式。但是为什么呢?理由很简单:保持第三方包的稳定。第三方包基本都会作版本更新,使用其他的约定方式则会存在一个问题:当前匹配的版本会变更。举个例子,假如我们用通配符的方式引入了monolog包(require {“monolog/monolog”:”*”}),现在项目中用的是1.0版本,隔了一阵子,monolog发布了2.0版本,而且与1.0版本的api有了明显的不兼容,我们在项目中执行了composer update命令,则会自动将版本更新为2.0版本,组件api改变了,原来的地方有可能就会出现报错。
至于如何知道第三方包的版本,我们可以直接在packagist搜索得到,可以自行选择引入的版本。
问题4:composer执行安装命令后一直停留在等待界面?
这里有些小技巧可以改进这个问题。首先就是命令的后面加上-vvv,就可以打印出具体的debug信息,实时地知道现在的运行情况;很多时候等待过久是因为遇到不翻墙下不了包的问题,这时可以通过设置包的源为中国镜像,具体可以参考这里。