本文主要包含几个部分
- Composer仓库讲述
- 为什么要搭建私有的Composer仓库
- 如何开发composer包
- satis搭建私有仓库
- satis的UI界面重构思路
- 参考文档
一、Composer仓库
- Composer
Composer是 PHP 用来管理依赖(dependency)关系的工具。你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer 会帮你安装这些依赖的库文件
- Composer仓库
Composer仓库是用来管理以及存储php拓展包的一个集合。如packagist.org.
- php拓展包的形式
- php底层语言编写的:一般使用pecl安装或采取源码安装方式。
- php编写的:一般可通过pear安装 或 Composer安装 或 手动引入
- 典型的例子:phpredis 与 predis
二、为什么要搭建私有的Composer仓库
-
首先列举几个很熟悉的场景
- 在项目当中不可避免的会用到一些常见的函数,比如说一个获取客户端ip的代码。一般开发会选择去百度、谷歌,然后一顿ctrl c + v ...接着就拷贝到各个项目当中,跑起来能用,ok没问题。但是过了一段时间,咦,原来这段代码有一个bug。A项目改一下、B项目也改一下,C项目忘记改了...
- 在公司内部的项目里,我们经常会发现多个项目之间会存在一些公用的模块。如,公司内部有多个C端,但是都有一个统一的数据接口模块。那么多个项目之间都会写重复调用这个模块接口的代码。我们可以在A项目中写了,拷贝到B、C....,但此时如果数据模块接口发生了变化,那就...
- 公司项目之间,前后端业务层甚至模型层,重复的代码很多,但是用的框架都是一样的...
- ...
-
上面说了这几个场景,在实际的开发工作当中很常见,总结来说存在以下几个问题:
- 代码质量角度:常用的函数,重用的模块代码,大家习惯了拷贝,代码质量很自然的少关注
- 开发效率角度:项目之间应用了重复的代码,拷贝接入效率低 或者 根本就不知道其他项目中有存在的轮子
- 维护成本角度:重复的代码使用,假如出现了bug或者需要迭代以适应新的需求,需要在一个个项目中调整 甚至还可能出现忘记的情况
- 开源角度:在工作当中,我们所开发的很多东西是不方便开源的
ps:其实上面说了那么多,最迫切需要搭建私有仓库的是最后一点...
- 针对上述的问题有几个初步方案:
- 在packagist上发布包:开源不符合,私有需要付费
- 直接composer.json中通过声明内部vcs的 respository:符合,但管理不方便,查找不方便
- 搭建一个私有的Composer仓库:符合,需要花点时间搭建维护
- toran proxy:不开源,有便捷操作的UI界面
- satis:开源,有UI界面,但是不是很方便操作,需要美化一下
PS:pear包同样也是php的包,但是已过时了,composer正值壮年。
三、如何开发composer包
上面讲了很多为什么要模块化、为什么要做composer包、为什么要搭建私有composer仓库,那么接下来我们首先看下怎么做一个自己的composer包以及回顾一下有哪些知识。
1.composer.json中一些常用的参数
- name
- 包名,一般包含两部分[vendor/name]。“/”前面代码发行的一个单位或大板块,后面的是包名字
- type
- 包的类型
- libray:拓展库,默认类型,最常用的(安装完默认会在root包中vendor目录下,什么是root包下面再说)
- project:项目,比如说laravel等一些框架提供了一些出事话项目的命令 composer create-project ...(此时发包就是定义这种类型,安装完就是一个root包)
- metapackage:当一个空的包,包含依赖并且需要触发依赖的安装,这将不会对系统写入额外的文件。因此这种安装类型并不需要一个 dist 或 source(官方说明)
- composer-plugin:一个安装类型为 composer-plugin 的包,它有一个自定义安装类型,可以为其它包提供一个 installler。详细请查看 自定义安装类型(官方说明)
- 包的类型
- description
- 包的描述,告诉别人这个包用来干嘛的
- license
- 包的许可协议
- authors
- 发行机构(个人)信息
- repositories
- 自定义资源库(默认情况下,composer会按照顺序进行资源查找,最后才检测默认的资源库)
- type:资源库类型
- path:本地资源包(支持绝对路劲、相对路径)
- vcs:git、svn等版本控制的资源包
- composer:composer资源镜像仓库下的资源包,如https://mirrors.aliyun.com/composer/、packagist.org
- package
- type:资源库类型
- 自定义资源库(默认情况下,composer会按照顺序进行资源查找,最后才检测默认的资源库)
- require
- 项目必须安装的依赖包
- require-dev
- 项目开发或测试环境下需要安装的依赖包
- autoload
- 自动加载映射定义,支持四种类型映射定义(在开发包时,可直接通过修改autoload配置进行包的引入进行调试)
- psr-0:支持psr-4命名空间到目录的映射、精确到文件的映射
- psr-4:支持psr-4命名空间到目录的映射、精确到文件的映射
- classmap:支持指定路径的文件映射扫描,也支持精确到文件
- files:指定加载文件,一般用于函数库加载
- 自动加载映射定义,支持四种类型映射定义(在开发包时,可直接通过修改autoload配置进行包的引入进行调试)
- autoload-dev:
- 测试环境下使用的自动加载映射定义,同上支持四种类型映射定义
- scripts
- 自定义脚本(仅root包中运作。在composer运行的生命周期当中触发的一些钩子脚本,跟git上面hook是一个道理。详细的可到官方文档中去查)
- config
- 配置项(composer的一些局部配置项,常用的比如composer config secure-http false)
- extra
- 额外的一些配置参数(配合scripts中使用)
2.composer的常用命令
-
composer install
- 说明:安装包依赖以及自动加载映射相关文件。存在composer.lock文件的情况下,此命令会按照composer.lock中锁定的依赖包版本号等信息直接安装,否则即按照composer.json中声明的一来信息进行安装
- 常用可选参数
- --no-dev:忽略composer.json下声明的require-dev包
- --dev:安装composer.json下声明的包
- --optimize-autoloader:将psr0/psr4规范下的自动加载转化为classmap的方式
- --no-scripts:跳过 composer.json 文件中定义的脚本
- 应用场景
- 一般用于项目初始化
-
composer update
- 说明:根据composer.json文件中的声明进行项目依赖更新、自动加载映射。
- 常用可选参数
- --no-dev:忽略composer.json下声明的require-dev包
- --dev:安装composer.json下声明的包
- --optimize-autoloader:将psr0/psr4规范下的自动加载转化为classmap的方式
- --no-scripts:跳过 composer.json 文件中定义的脚本
- 应用场景
- 特定的依赖包需要更新。==请谨慎直接使用composer update,这会导致所有依赖包升级至依赖的最高版本,可能会对项目造成不可预估的损害==
-
composer require package_name[:version]:
- 说明:安装新包
- 常用可选参数:
- --dev: 安装 require-dev 字段中列出的包。
- --no-update: 禁用依赖关系的自动更新(在确保项目能运作的情况下,可使用此命令)
- 应用场景:
- 引入新包
-
composer dumpautoload:
- 说明:重新生成各依赖包的自动加载映射文件
- 常用可选参数:
- --optimize (-o): 转换 PSR-0/4 autoloading 到 classmap 获得更快的载入速度。这特别适用于生产环境,但可能需要一些时间来运行,因此它目前不是默认设置。
- --no-dev: 禁用 autoload-dev 规则。
-
常用的全局参数
- -v:表示正常输出
- -vv:表示更详细的输出
- -vvv:debug级别的信息(一般装包时候,卡住了,不知道什么原因,可以加上此命令看看)
//来个示例说明一下
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"type": "project",
"require": {
"php": ">=7.0.0",
"barryvdh/laravel-debugbar": "^3.2",
"bkqw_tech/ucenter": "^2.0",
"encore/laravel-admin": "^1.6",
"fideloper/proxy": "~3.3",
"intervention/image": "^2.4",
"jacobcyl/ali-oss-storage": "^2.1",
"laravel/framework": "5.5.*",
"laravel/tinker": "~1.0",
"maatwebsite/excel": "~2.1.0",
"mrgoon/aliyun-sms": "dev-master",
"overtrue/laravel-wechat": "^4.0",
"predis/predis": "^1.1",
"simplesoftwareio/simple-qrcode": "^2.0",
"topthink/think-helper": "^1.0"
},
"require-dev": {
"filp/whoops": "~2.0",
"fzaninotto/faker": "~1.4",
"mockery/mockery": "~1.0",
"phpunit/phpunit": "~6.0",
"symfony/thanks": "^1.0"
},
"autoload": {
"files": [
"app/Support/Helpers/common.php"
],
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"extra": {
"laravel": {
"dont-discover": [
]
}
},
"scripts": {
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate"
],
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover"
]
},
"config": {
"preferred-install": "dist",
"sort-packages": true,
"optimize-autoloader": true,
"secure-http": false
},
"repositories": {
"ucenter": {
"type": "composer",
"url": "http://10.1.11.88:7075/"
}
}
}
ps:大家可以了解一下vendor目录下composer文件夹的大概结构,大概了解一下composer的原理。知道原理能让我们做起来更加得心应手。
3.初始化composer包
- 命令行初始化
- 手动创建composer.json文件
{ "name": "adam/composertest", "description": "这是一个测试包", "type": "library", "authors": [ { "name": "Adam", "email": "wangyi@163.com" } ], "require": {} }
包的结构就不用多说了,只要符合几种composer的自动加载机制就可以了,没什么特别限制
4.发布包
这里说一下在packagist上发布一个包,下面再说搭自己的私有仓库
1.先把自己的项目发布到vcs的一个托管平台,如github,gitee
2.注册一个packagist账号
3.进入https://packagist.org,点击submit,提交,完事
就这么简单,关于包的版本管理,可以拓展研究一下
5.安装包
直接composer require <package_name>:dev-master。这里说下composer安装包的几种方式声明
(1).本地安装声明
{
"name": "adam/project",
"description": "这是一个测试包",
"type": "project",
"authors": [{
"name": "Adam",
"email": "wangyi@163.com"
}],
"require": {},
"repositories": {
"composertest": {
"type": "path",
"url": "packages1/composertest"//相对路径或绝对路径
}
}
}
(2).vcs安装声明
{
"name": "adam/project",
"description": "这是一个测试项目",
"type": "project",
"authors": [{
"name": "Adam",
"email": "wangyi@163.com"
}],
"require": {},
"repositories": {
"easywechat": {
"type": "vcs",//vcs、git、svn
"url": "https://github.com/w7corp/easywechat.git"//远程版本仓库地址
}
}
}
(3).composer安装声明
{
"name": "adam/project",
"description": "这是一个测试项目",
"type": "project",
"authors": [{
"name": "Adam",
"email": "wangyi@163.com"
}],
"require": {},
"repositories": {
"easywechat": {
"type": "composer",
"url": "https://packagist.org/"//composer仓库地址
}
}
}
(4).其他安装方式声明
{
"name": "adam/project",
"description": "这是一个测试项目",
"type": "project",
"authors": [{
"name": "Adam",
"email": "wangyi@163.com"
}],
"require": {},
"repositories": {
"easywechat": {
"type": "composer",
"url": "https://packagist.org/"//composer仓库地址
}
}
}
四、satis搭建私有仓库
1.安装satis
- git安装:git clone https://github.com/composer/satis.git
- composer安装:composer create-project composer/satis --stability=dev
2.配置公钥
如果将要引入的依赖包是一个私有vcs项目,请务必进行配置。如果你引入的包都是公有项目可以跳过此步骤(参考配置文档:https://gitee.com/help/articles/4181)。
ssh-keygen -t rsa -C "xxxxx@xxxxx.com"
# Generating public/private rsa key pair...
cat ~/.ssh/rsa_id.pub
# 将公钥复制到你的托管平台ssh公钥设置里面
3.初始化satis
- 在项目根目录运行 php bin/build init
- 根据提示输入自己的仓库名以及原地址首页(后续再webpage上可以看到安装包的json展示的即homepage地址)
{
"name": "adam's composer repository",
"homepage": "http://composer.cc",
"repositories": [],
"require-all": true
}
4.构建satis UI界面
(1) 构建:
-
方式一:
- 修改satis.json文件
{ "name": "adam", "homepage": "https://adamoba.com", "repositories": [ { "type": "vcs", "url": "http://10.1.11.88:8024/bkqw_tech/ucenter.git" } ], "require-all":true, "config":{ "secure-http":false } }
- 运行构建命令
php bin/satis build --repository-url http://10.1.11.88:8024/bkqw_tech/ucenter.git satis.json ./web
-
方式二:
- 修改satis.json文件
{ "name": "adam", "homepage": "https://adamoba.com", "repositories": [ { "type": "vcs", "url": "http://10.1.11.88:8024/bkqw_tech/ucenter.git" } ], "require":{ "bkqw_tech/ucenter":"*" }, "config":{ "secure-http":false } }
- 运行构建命令
php bin/satis build --repository-url http://10.1.11.88:8024/bkqw_tech/ucenter.git satis.json ./web
如果源中包含了http协议,需增加secure-http为false的配置项
说明:
- 如果直接build,不加入repository-url或者不修改require-all参数的情况下,satis会扫描所有的respositories(包括composer的默认源,不清楚原因),会导致构建非常非常慢
- 如果加入了repository-url的情况下,satis只会扫描指定的vcs地址
(2)配置一个php运行环境,运行时目录指向到web目录下(示例域名:http://composer.cc)
(3) 访问:http://composer.cc,看到如下界面,即成功
image4.发布包到satis
(1)修改配置文件:
- 命令行
php bin/satis add http://10.1.11.88:8024/bkqw_tech2/ucenter2.git
- 编辑配置文件:
{
"name": "adam",
"homepage": "https://adamoba.com",
"repositories": [
{ "type": "vcs", "url": "http://10.1.11.88:8024/bkqw_tech/ucenter.git" },
{ "type": "vcs", "url": "http://10.1.11.88:8024/bkqw_tech2/ucenter2.git" }
],
"require-all":all
"config":{
"secure-http":false
}
}
(2) 构建
- 命令行 php bin/satis build --repository-url http://10.1.11.88:8024/bkqw_tech2/ucenter2.git satis.json ./web
- 访问:http://composer.cc
6.在项目中引入satis的包
//这一段即http://composer.cc种,add repositories那一段展开json
{
"repositories": [{
"type": "composer",
"url": "https://composer.cc"
}]
}
//或通过命令行进行局部配置 composer config repositories.ucenter composer https://adamoba.com
{
"repositories": {
"ucenter":{
"type": "composer",
"url": "http://composer.cc"
}
}
}
// 因为此处repository的里面的包基本都是http协议,所以外加如一行
{
"config":{
"secure-http":false
}
}
// 或通过命令行 composer conifg secure-http false
// 接着composer require xxx
//(如果项目没有打上标签,composer require package_name:dev-master)
image关于satis命令如何使用,直接在运行php bin/satis 就可以查看到相关的说明了。
五、satis改造:可视化操作添加源
如果公司内部成员都会发布一些包到这个satis站点里面,让大家都去熟悉satis可能不那么理想。那接下来就通过对satis项目的进行一些调整,以达到可视化操作添加源的目的(如packagist.com中,只需要贴入地址就可以,提交一个源到其中过了)
- 思路
- 打开satis目录下的views文件夹,找到index.html.twig(这个是satis首页的模板)
- 增加前端页面:
- 每一个包的item增加删除按钮、更新按钮
- 增加发布新包页面(为了便捷,我拷贝了一下packagis.com的页面)
- 增加后端处理脚本:
- 删除包:通过php的exec函数调用 “php bin/satis purge xxxx”,再php调用satis build
- 更新包:通过php的exec函数执行“php bin/satis build --respository-url=url_name satis.json ./web pacakage_name”
- 增加包:通过php的exec函数执行“php bin/satis add --respository-url=url_name --type=vcs --name=package_name”,最后执行更新包的命令
另外的思路实现vcs包添加与更新:以gitlab为例,配置gitlab的webhook,在每次接收到新推送时,触发对应的satis url,检测到包存在则执行更新命令,包不存在则执行新增命令
六、参考文档
- 基于 Composer 的 PHP 模块化开发
- 正确的 Composer 扩展包安装方法
- composer.json的基础架构
- composer命令行的使用
- satis简介
网友评论