如何发布一个自己的Composer依赖包

Composer
213
0
0
2024-03-11
标签   Composer

Composer是 用PHP开发的用来管理项目依赖的工具,当你在项目中声明了依赖关系后,composer可以自动帮你下载和安装这些依赖库,并实现自动加载代码。

工作原理

主要由三个部分组成:命令行工具、包仓库、代码库:

命令行

命令行指的就是 composer 的各种命令。如:创建项目(create-project)、引入扩展包(require)、移除扩展包(remove)、清空缓存(clear-cache)等

仓库

  • Packagist:官方仓库,也就是我们平常说的 Composer 源,它的作用是存储这些包的信息,版本,代码来源,依赖,作者,主页等信息。官网是 packagist.org, 你也可以将自己的包发布在上面,这样 Composer 工具就能搜索与安装你的包了
  • 公有仓库:https://packagist.org
  • 私有仓库:https://packagist.com
  • Repository:代码存储库仓库,Packagist 支持公开与私有仓库,通常是 GitHub 作为代码仓库,当然也可以是 Gitee

自动加载

只需要执行composer命令拉取扩展包,即可实现自动加载代码,包依赖管理和使用自动加载,PSR-0 和 PSR-4 自动加载规范。

步骤

要发布一个软件包,我们首先必须将它托管在版本控制系统存储库中。源代码应该放在根目录下,composer.json文件应该根据下面的规则进行适当的配置。之后,您可以在不同的平台上提交您的软件包。

Step1. 创建代码仓库

在自己的github创建一个公共仓库,这里仓库名为hello,创建好后克隆代码到自己本机电脑

git clone git@github.com:Tinywan/hello.git

Step2. 初始化 composer.json

D:\dnmp\www\hello> composer init

  Welcome to the Composer config generator

This command will guide you through creating your composer.json config.

// 包名
Package name (<vendor>/<name>) [tinywan/hello]:
// 包描述
Description []: 开源技术小栈如何构建自己的Composer依赖包

// 作者信息
Author [Tinywan <756684177@qq.com>, n to skip]:

// 包类型和协议直接回车就好了
Minimum Stability []:

// 包的依赖,如最低PHP要求
Package Type (e.g. library, project, metapackage, composer-plugin) []: library
License []:

Define your dependencies.

Would you like to define your dev dependencies (require-dev) interactively [yes]? no
Add PSR-4 autoload mapping? Maps namespace "Tinywan\Hello" to the entered relative path. [src/, n to skip]:

{
    "name": "tinywan/hello",
    "description": "开源技术小栈如何构建自己的Composer依赖包",
    "type": "library",
    "autoload": {
        "psr-4": {
            "Tinywan\\Hello\\": "src/"
        }
    },
    "authors": [
        {
            "name": "Tinywan",
            "email": "756684177@qq.com"
        }
    ],
    "require": {}
}

Do you confirm generation [yes]?
Generating autoload files
Generated autoload files
Would you like the vendor directory added to your .gitignore [yes]?
PSR-4 autoloading configured. Use "namespace Tinywan\Hello;" in src/
Include the Composer autoloader with: require 'vendor/autoload.php';
最后生成的composer.json文件内容
{
    "name": "tinywan/hello",
    "description": "开源技术小栈如何构建自己的Composer依赖包",
    "type": "library",
    "autoload": {
        "psr-4": {
            "Tinywan\\Hello\\": "src/"
        }
    },
    "authors": [
        {
            "name": "Tinywan",
            "email": "756684177@qq.com"
        }
    ],
    "require": {}
}
项目目录结构

  • src/ 存放源代码文件
  • vendor/ 存放第三方依赖
  • composer.json 定义项目的元数据和依赖信息
  • README.md 项目的说明文档
  • 其他必要的文件和目录

Step3. 实现包功能

这里实现一个简单的加密工具类Encryption

<?php
/**
 * @desc 加密工具类
 * @author Tinywan(ShaoBo Wan)
 * @date 2023/12/30 14:27
 */
declare(strict_types=1);

namespace tinywan\hello;

class Encryption
{
    /** AES-128-ECB 加密方式*/
    public const AES_128_ECB = 'AES-128-ECB';

    /**
     * @desc 加密
     * @param string $data 加密的数据
     * @param string $key 密钥,必须是16、24或32个字符长度
     * @param string $algo 加密方式
     * @param string $iv 初始向量(IV)
     * @return string
     * @author Tinywan(ShaoBo Wan)
     */
    public static function encrypt(string $data, string $key, string $algo = self::AES_128_ECB, string $iv = ''): string
    {
        $encryptedBytes = openssl_encrypt($data, $algo, $key, OPENSSL_RAW_DATA);
        return base64_encode($encryptedBytes);
    }

    /**
     * @desc 解密
     * @param string $data
     * @param string $key 密钥,必须是16、24或32个字符长度
     * @param string $algo 加密方式
     * @param string $iv 初始向量(IV)
     * @return false|string
     * @author Tinywan(ShaoBo Wan)
     */
    public static function decrypt(string $data, string $key, string $algo = self::AES_128_ECB, string $iv = '')
    {
        return openssl_decrypt(base64_decode($data), $algo, $key, OPENSSL_RAW_DATA);
    }
}

Step4.编写单元测试用例

PHPUnit是一个轻量级的PHP测试框架,单元测试是几个现代敏捷开发方法的基础,使得PHPUnit成为许多大型PHP项目的关键工具。

安装PHP测试框架包phpunit/phpunit

composer require --dev phpunit/phpunit

EncryptionTest.php用例

<?php
/**
 * @desc EncryptionTest
 * @author Tinywan(ShaoBo Wan)
 * @email 756684177@qq.com
 * @date 2023/12/29 23:46
 */

declare(strict_types=1);

class EncryptionTest extends \PHPUnit\Framework\TestCase
{
    public function test()
    {
        $data = '开源技术小栈';
        $key = '53vYPpTJIR1aYFiFh0PppZzF';

        /** 加密*/
        $encrypt = \tinywan\hello\Encryption::encrypt($data, $key);
        self::assertIsString($encrypt);

        /** 解密*/
        $decrypt = \tinywan\hello\Encryption::decrypt($encrypt, $key);
        
        // 判断解密明文是否和预期的相等
        self::assertEquals($decrypt, $data);
    }
}
运行这个单元测试,在命令行下输入代码
$ vendor/phpunit/phpunit/phpunit tests/EncryptionTest.php 
PHPUnit 9.6.15 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 00:00.007, Memory: 4.00 MB

OK (1 test, 2 assertions)
结果中最重要的用红色标出的结果,点号.代表一个用例通过(即assert系列函数都通过)
如果将上面的测试用例改为不等于self::assertNotEquals(decrypt, data);,则运行结果为:
$ vendor/phpunit/phpunit/phpunit tests/EncryptionTest.php 
PHPUnit 9.6.15 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 00:00.010, Memory: 4.00 MB

There was 1 failure:

1) EncryptionTest::test
Failed asserting that '开源技术小栈' is not equal to '开源技术小栈'.

D:\dnmp\www\hello\tests\EncryptionTest.php:26

FAILURES!
Tests: 1, Assertions: 2, Failures: 1.

Step4. 提交代码到 GitHub

$ git commit -m "init"
[main ffed98a] init
 13 files changed, 1833 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 .idea/.gitignore
 create mode 100644 .idea/hello.iml
 create mode 100644 .idea/inspectionProfiles/Project_Default.xml
 create mode 100644 .idea/modules.xml
 create mode 100644 .idea/php-test-framework.xml
 create mode 100644 .idea/php.xml
 create mode 100644 .idea/vcs.xml
 create mode 100644 .phpunit.result.cache
 create mode 100644 composer.json
 create mode 100644 composer.lock
 create mode 100644 src/Encryption.php
 create mode 100644 tests/EncryptionTest.php

可以看出以上提交了好多无效的代码,如.idea目录,这里修改一下忽略提交文件.gitignore,内容如下:

build
vendor
.idea
.vscode
.phpunit*
composer.lock

Step5. 提交至 Packagist

Packagist 为 composer 默认获取包元数据信息的地址,从 Packagist 获取到元数据信息后,再从 GitHub 上拉取代码。因此,当把你开发的包上传至 GitHub 后还需要将其在 Packagist 注册。

一旦你的包发布到Packagist上,其他人就可以通过Composer安装你的包,并在他们的项目中使用你的代码。

提交至 Packagist 三个步骤
  • 注册帐号(有的话直接进行下一步)
  • 在https://packagist.org/packages/submit 提交开发包

提交成功

Step6. 使用包

一旦提交的包在Packagist发布了,则可以通过composer直接安装使用

composer require tinywan/hello dev-main
由于没有发布正式包,这里拉取包先要指定dev-main分支
composer require tinywan/hello dev-main
./composer.json has been updated
Running composer update tinywan/hello
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
  - Locking tinywan/hello (dev-main c6f43d0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 4 installs, 30 updates, 3 removals

如果要发布一个正式版本,需要在自己依赖包打标签tag

// 打标签
$ git tag v0.1

// 标签推送远程仓库
$ git push origin v0.1
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:Tinywan/hello.git
 * [new tag]         v0.1 -> v0.1

这时候再去拉取默认版本,就是刚才打标签的v0.1版本了

小结

以上是一个简单的构建自己的Composer依赖包的步骤,通过 composer 来管理 PHP 的依赖,通过编写 composer package 去扩展自己的类库,通过引入其他的类库来填充自己的功能,就不用重复造轮子了。当然还有更多的细节和高级用法可以根据具体情况进行调整。希望对你有所帮助!