如何使用Composer创建待发布代码库

现代PHP发展过程中,最初原始的文件拷贝、代码Ctrl+C/V的分发模式,phpear分发模式,再发展到composer横空出世,现代PHP库依赖管理通过composer解决各类库的版本依赖管理。

下文介绍如何打包发布自己的代码库:

新建待发布代码包

初始化项目

  • composer init
  • 修改后的composer.json文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"name": "fivezh/utils",
"description": "utils",
"type": "library",
"authors": [
{
"name": "fivezh",
"email": "fivezh@gmail.com"
}
],
"require": {
"guzzlehttp/guzzle": "~6.0"
}
}

PSR-4配置

  • 新增目录src/Rrc/Hello.php
  • composer.json增加psr-4的autoload
1
2
3
4
5
"autoload" :{
"psr-4":{
"Rrc\\":"src/Rrc"
}
}

更新命名空间

  • 执行composer dump-autoload更新autoload文件,将更新vendor/composer/autoload_psr4.php
1
2
3
4
5
6
7
return array(
'Rrc\\' => array($vendorDir . '/rrc/c2bUtils/src/Rrc'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
);

编写TestCase

  • 增加phpunit包
1
2
3
"require-dev": {
"phpunit/phpunit": "^6.2"
}
  • 增加phpunit.xml

设置bootstarp加载vendor/autoload.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
>
<testsuites>
<testsuite name="Application Test Suite">
<directory>./tests</directory>
</testsuite>
</testsuites>
<php>
<env name="TEST_CASE" value="testing"/>
</php>
</phpunit>
  • 编写testcase测试用例

新建文件test\DingMsg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use PHPUnit\Framework\TestCase;
use Rrc\DingMsg;

class DingMsgTest extends TestCase
{
public function testPushSingleMsg()
{
$alarm = new DingMsg();
try {
$res = $alarm->pushGroupRobotMsg('invalid_access_token',
'hello world', ['18612345678'], false);
$this->assertEquals(false, $res);
} catch (\Exception $e) {
$this->fail('异常:'.$e->getMessage());
}
}

}

通过执行phpunit则运行tests/下全部测试用例

至此,完整的composer.json文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"name": "rrc/c2bUtils",
"description": "c2b utils",
"type": "library",
"authors": [
{
"name": "zhangxiaowu",
"email": "zhangxiaowu@renrenche.com"
}
],
"require": {
"guzzlehttp/guzzle": "~6.0"
},
"require-dev": {
"phpunit/phpunit": "^6.2"
},
"autoload" :{
"psr-4":{
"Rrc\\":"src/Rrc"
}
}
}

发布到svc仓库或packagelist

上传代码库至私有仓库或github

一般企业内部私有仓库,则将代码推送至私有仓库远程分支

1
2
3
4
5
6
git init
git remote add origin git@github.com:yourusername/yourlibraryname.git
git add --all
git commit -m "initial files"
git tag -a v1.0.0 -m "initial release"
git push -u origin master

发布至packagelist

访问packagelist/package/submit,注册、登录、提交Github地址则会被packagelist收录。

详细参考:如何创建一个自己的 Composer 库

新项目通过composer引用代码库

vsc托管方式

如果代码库是内部托管(git/svn/hg等),可通过repositories形式引入包。

  1. 修改新项目的composer.json,增加依赖库引入
1
2
3
4
5
6
7
8
9
"repositories": {
"c2bUtils": {
"type": "vcs",
"url":"git@gitlab.renrenche.com:zhangxiaowu/c2b_php_utils.git"
}
},
"require": {
"rrc/c2bUtils": "^1.0"
}

注意:

  • repositories中的url仅仅是仓库的地址和包名无关
  • require中为包名,即库项目的composer.json中的name
  1. 执行composer install -vvv安装依赖库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> composer install -v
Loading composer repositories with package information Updating dependencies (including require-dev)
Dependency resolution completed in 0.001 seconds
Analyzed 237 packages to resolve dependencies
Analyzed 303 rules to resolve dependencies
Package operations: 5 installs, 0 updates, 0 removals
Installs: guzzlehttp/promises:v1.3.1, psr/http-message:1.0.1, guzzlehttp/psr7:1.4.2, guzzlehttp/guzzle:6.3.3, rrc/c2bUtils:1.0.0
- Installing guzzlehttp/promises (v1.3.1) Loading from cache Extracting archive
- Installing psr/http-message (1.0.1) Loading from cache Extracting archive
- Installing guzzlehttp/psr7 (1.4.2) Loading from cache Extracting archive
- Installing guzzlehttp/guzzle (6.3.3) Loading from cache Extracting archive
- Installing rrc/c2butils (1.0.0) Cloning 1ccfd6bcfd95cd3b1ea884594c9f58f8fe7283fd
guzzlehttp/guzzle suggests installing psr/log (Required for using the Log middleware)
Writing lock file
Generating autoload files

此时如果查看vendor/composer/autoload_psr4.php,应该可以看到新增包的PSR-4映射已经加入到此文件中。

packagelist方式

如果代码库已提交至packagelist.org,则已被composer可检索。
就如同使用guzzlehttp/guzzle包一样,直接通过composer require apptut/web-util -vvv引入进来即可。

问题记录

通过composer require进来后,autoload无法找到对应命名空间

这个问题出发点在于,未对repositories中的type正确设置:

  • composer:composer类型的库
  • vsc:从git/svn/hg获取
  • pear:从pear获取资源
  • package:未提供composer支持,需手动进行autoload设置

如果自有代码仓库,且包含composer.json支持,则配置repositories时指定类型为vsc,可自动加载依赖项目的autoload;
如果自有代码仓库,无composer.json支持,说明是静态冷文件,无法自动加载,需要引入代码仓库后,手动进行autoload的设置,classmap/psr-4/files等各种形式都可以。

通过repositories安装库时无法找到

  • composer install错误信息如下he requested package could not be found in any version, there may be a typo in the package name.
  • 可能的问题:
    • 包名错误
    • 未找到满足要求的代码库版本
  • 解决:composer依赖tag信息选择版本,代码库必须有对应tag信息
  • git tag -a v1.0.0 -m "initial release"
1
2
3
4
5
6
7
8
9
Your requirements could not be resolved to an installable set of packages.

Problem 1
- The requested package rrc/c2b_utils could not be found in any version, there may be a typo in the package name.

Potential causes:
- A typo in the package name
- The package is not available in a stable-enough version according to your minimum-stability setting
see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.

参考文档