composer私有仓库建设

正在公司推动composer私有仓库,整理了一些思路如下。

背景

  • 新建项目没有规范,随手拷贝已有项目已成”乱象”
  • 已有项目对框架侵入严重,每个项目的框架代码都不相同
  • 基于复制粘贴复制公共库,代码不一致,无法统一升级更新,效率低下

目标

  • 统一项目脚手架:命令一键创建新项目
  • 统一基础公共库:命令一键安装与更新依赖

路线图

  • composer satis + gitlab 私有仓库搭建
  • composer工具培训
  • 脚手架接入composer仓库
  • 图片处理、link处理等常见痛点封装为公共库,接入composer仓库

架构

基于composer+gitlab搭建整套架构,其中composer类似于java maven、python pip、nodejs npm,是一款可靠的php包管理工具。

  • 客户端:composer完成依赖配置、安装、更新
  • 私有仓库:composer satis搭建,仅维护私有包的索引信息
  • 代码托管:gitlab,存储库代码,维护分支与tag

composer安装与使用

安装

安装成功后,可以直接使用composer命令。

使用Windows的同学可以通过Phpstorm直接安装与管理composer。

创建项目

执行composer init来初始化一个空白项目,也称为”root项目”。

根据提示填入各种信息即可,最终会生成composer.json配置文件。

生成后的composer.json文件如下:

安装外部依赖

作为root项目,通常只关心自己依赖哪些包、包的版本是什么。

默认composer只会在官方仓库中寻找你要安装的包,例如安装一个elasticsearch的客户端:

包的命名遵循:”组织名/包名”,是全局唯一的,冒号之后是版本控制,具体规则后面会提供学习链接。

安装这样的第三方包不需要做额外的配置,composer工具总是会到官方仓库中寻找你要安装的包。

现在composer.json如下:

安装内部依赖

安装私有仓库的包略有不同,首先需要配置composer私有库的地址,编辑上述composer.json:

现在尝试安装一个私有的包:

composer工具会到私有仓库查找这个包,如果没找到还会去默认的官方仓库查找。

未来可以移除secure-http选项,因为最终私有仓库域名会改为https协议。

常用命令

  • 初始化composer.json:
  • 安装依赖
  • 删除依赖
  • 升级依赖(先修改composer.json中的依赖配置)
  • 清空缓存

引入composer自动加载

composer安装的包文件存储在vendor目录。

为了在自己的项目中使用安装的依赖库,需要加载composer的autoload函数,这样才能访问到包中的类和方法:

调用包中的方法

baidu\common\Author类会被自动加载到PHP中,这里调用了它的静态方法name()。

参考资料

composer包制作

下面介绍如何制作一个composer包,最终制作好的包既可以发布到公共仓库,也可以发布到私有仓库。

我最终希望发布包到composer私有仓库,所以包的代码也托管在私有的gitlab中才安全。

在gitlab创建项目

在gitlab上创建一个叫做php-common的项目。

希望发布一个包叫做”baidu/common”,因此我们依旧通过composer init来初始化一个composer.json:

该包当然也可以通过require来依赖其他的包,即二级依赖。

composer包名是name指定的,与gitlab项目名无关。

开发库代码

composer包建议把源代码放在src目录下:

我希望整个包下的所有class文件,均采用baidu\common的命名空间前缀。

以src/Author.php为例:

配置类自动加载

为了composer可以找到加载到baidu\common\Author这个类,需要在composer.json中定义”命名空间前缀”与”类文件路径”之间的关系。

我们遵循psr-4类加载规范,以baidu\common命名空间为前缀的class,会在src目录下查找。

当其他项目调用baidu\common\Author类时,composer会在”vendor/baidu(组织名)/common(包名)/src/”下加载Author.php文件。

编写测试

composer建议把测试代码放在test目录下:

我编写一个很简单的调用示例:

就像其他项目一样,我们引入composer的autoload,然后就可以访问对应的类。

satis安装

satis用于构建一个私有仓库,它通过扫描gitlab上的版本库信息建立仓库索引,并将索引提供给composer客户端获取。

代码最终依旧是客户端直接向gitlab下载的,相关的权限验证依旧由gitlab把控。

下载satis

配置satis

在satis目录下放置一个satis.json配置文件,在其中罗列所有gitlab上希望发布的包信息:

  • name: 私有仓库的名字,最终会展现在UI界面上
  • homepage: 私有仓库的服务地址,未来会替换为https协议
  • repositories:所有要发布的包地址
  • require: 指定索引哪些包的哪些版本,这里我指定索引baidu/common包的所有版本。

千万不要使用require-all选项,而是应该在require中罗列每个包(require-all的意思是将官方仓库的所有包索引到本地,对我们毫无意义)。

因为我的gitlab采用帐号密码认证,所以需要为composer配置gitlab帐号密码:

帐号密码被保存在~/.composer/auth.json中。

定时更新仓库索引

satis只是一个命令行工具,我们需要定时让satis扫描gitlab上的版本变化,更新仓库索引信息。

将下面的任务添加到crontab(非root用户):

该命令可以防止并发执行多个satis,同时会将构建好的静态索引文件存储到repo目录。

实际上仓库就是一个索引文件package.json文件,它描述了完整的gitlab包索引信息:

  • dev-master:非stable的开发中master分支
  • 1.0.0:stable版本
  • 1.0.1:stable版本,修复了1.0.0版本中的一些问题

配置Web

为了让composer客户端可以访问到私有仓库的索引,以及为了有一个可视化的界面查看索引,我们需要配置nginx指向repo目录:

打开浏览器访问http://packagist.baidu.com即可看到所有被索引的包与版本信息。

参考资料

其他

composer脚手架

我们可以将一份标准模板web框架上传到gitlab项目中,并将项目发布为一个composer包。

我们知道,composer require命令安装的包都会被存储到vendor目录下,并提供autoload自动加载。

除此之外,其实composer还提供了create-project命令,它专门用于创建模板项目。

它的工作原理是:

  • git clone直接下载包代码到当前目录
  • composer update下载模板项目的依赖包
  • 执行composer.json中配置的一些钩子函数,做一些自定义操作(比如创建目录)

这个过程我们可以手动操作,只是composer更方便:

上述命令将baidu/common项目下载到本地的my-common目录,需要指定仓库地址为我们的私有仓库,并且下载完成后删除.git目录。

主流的PHP开源框架均采用composer来帮助开发者初始化项目,一般思路如下:

  • 框架核心模块分别独立发布在多个composer包里
  • 框架脚手架发布单独的composer包,预建了controller、model等目录,并配置composer.json定义二级依赖各个独立的框架核心包
  • 使用脚手架的用户可以通过composer update一键更新所有框架核心代码,实现了业务与框架的分离

语义化版本控制

satis会自动识别gitlab上的分支与tag。

作为tag发布的版本均被composer视为stable稳定版本,例如1.0.0,1.0.1的tag会被Composer索引为1.0.0与1.0.1。

在普通分支中的代码是非stable(非稳定)版本,composer会在索引时在它们的分支名前增加dev-前缀,例如master分支的composer版本为dev-master。

我们总是应该依赖stable版本,而不是依赖一个开发中的dev-master版本。

另外,简单解释一下语义化版本a.b.c:

  • a:主版本,一般与前一个主版本存在不兼容的功能
  • b:次版本,发布的功能能够向下兼容
  • c:补丁版本:修复先有功能问题

参考资料


最后附上一开始做的一个例子:

  1. 制作一个composer包:https://github.com/owenliang/first-composer-package
  2. 搭建私有composer仓库:https://github.com/owenliang/satis-composer-repository
  3. 从私有仓库安装包:https://github.com/owenliang/satis-composer-usage

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~