一组小巧且实用的组件

3.1.0 2024-07-24 10:29 UTC

README

Build Status

此包是我们每天使用的“小”PHP实用工具的游乐场。它们不够复杂或庞大到需要单独的包,但它们很有用,也许有一天会发展成为完整的包。这就是为什么它们都直接命名空间在 ActiveCollab 命名空间下,而不是 ActiveCollab\Utils

包含内容

  1. 类查找器
  2. 配置加载器
  3. Cookie
  4. 当前时间戳
  5. 加密器
  6. 防火墙
  7. JSON
  8. 值容器
  9. URL

类查找器

ActiveCollab\ClassFinder\ClassFinderInterface - 此接口及其实现提供了一种轻松扫描目录以查找扩展指定类别的类的简便方法,以及可选的这些类的对象实例化。它对于在CLI应用程序、控制器、组件等中自动发现命令类非常有用。

<?php

declare(strict_types=1);

namespace MyApp;

use ActiveCollab\ClassFinder\ClassFinder;

$command_classes = (new ClassFinder())->scanDirForClasses(
    new ClassDir(
        __DIR__ . '/commands',
        'MyApp\\Commands',
        Command::class,
    ),
);

foreach ($command_classes as $command_class) {
   // Do something with the command class.
}

配置加载器

ActiveCollab\ConfigLoader\ConfigLoaderInterface - 接口指定了一种加载应用程序配置的方法,同时指定要求,如选项存在性或非空值要求。

基本用法

以下示例演示了配置加载器的基本用法(我们将使用 ArrayConfigLoader,但您可以使用任何其他配置加载器实现)

<?php

declare(strict_types=1);

namespace MyApp;

use ActiveCollab\ConfigLoader\ArrayConfigLoader;

$config_loader = (new ArrayConfigLoader('/path/to/file.php'))
    ->requirePresence('APPLICATION_VERSION')
    ->requireValue('LOG_HANDLER')
    ->requirePresenceWhen('LOG_HANDLER', 'graylog', 'GRAYLOG_HOST', 'GRAYLOG_PORT')
    ->requireValueWhen('LOG_HANDLER', 'file', 'LOG_DIR_PATH')
    ->load();

if ($config_loader->hasValue('LOG_HANDLER')) {
    if ($config_loader->getValue('LOG_HANDLER') == 'file') {
        print 'Log dirs path is ' . $config_loader->getValue('LOG_DIR_PATH') . ".\n";
    } else {
        print 'Logs are sent to Graylog at ' . $config_loader->getValue('GRAYLOG_HOST') . ':' . $config_loader->getValue('GRAYLOG_PORT') . ".\n";    
    }
} else {
    print "Log handler not present.\n"; // Impossible case, because we value is required. Using this just to demonstrate `hasValue()` method.
}

如上例所示,您可以通过调用 hasValue() 检查选项值的存在。要获取选项的值,请调用 getValue()

验证器

有四种主要验证器可以用于设置配置选项要求,并让配置加载器验证是否所有所需的选项都存在

  1. requirePresence - 要求选项存在。值可以是空的
  2. requireValue - 要求选项存在,并且值不能为空
  3. requirePresenceWhen - 条件性存在要求;当选项 X 的值为 Y 时,要求选项 Z 存在
  4. requireValueWhen - 条件性值要求;当选项 X 的值为 Y 时,要求选项 Z 存在,并且其值不能为空

所有四个验证器都接受所需字段的数组

<?php

declare(strict_types=1);

namespace MyApp;

use ActiveCollab\ConfigLoader\ArrayConfigLoader;

(new ArrayConfigLoader('/path/to/file.php'))
    ->requirePresence('X', 'Y', 'Z')
    ->requireValue('A', 'B', 'C')
    ->requirePresenceWhen('LOG_HANDLER', 'graylog', 'X', 'Y', 'Z')
    ->requireValueWhen('LOG_HANDLER', 'file', 'A', 'B', 'C');

注意:添加条件要求的验证器将使条件选项成为必需的,并且它的值不允许为空。

验证错误

如果发生验证错误(必需的选项不存在,或者当需要值时它为空),将抛出异常

<?php

declare(strict_types=1);

namespace MyApp;

use ActiveCollab\ConfigLoader\ArrayConfigLoader;
use ActiveCollab\ConfigLoader\Exception\ValidationException;

try {
    (new ArrayConfigLoader('/path/to/file.php'))
        ->requirePresence('APPLICATION_VERSION')
        ->requireValue('LOG_HANDLER')
        ->requirePresenceWhen('LOG_HANDLER', 'graylog', 'GRAYLOG_HOST', 'GRAYLOG_PORT')
        ->requireValueWhen('LOG_HANDLER', 'file', 'LOG_DIR_PATH')
        ->load();
} catch (ValidationException $e) {
    print 'Config could not be loaded. Reason: ' . $e->getMessage() . "\n";
}

注意:可以在调用 load() 方法之前设置要求。如果尝试在加载配置选项之后设置要求,将抛出异常。

Cookie

ActiveCollab\Cookies\CookiesInterface - 此接口及其实现基于 dflydev-fig-cookies 构建,为使用PSR-7消息的PHP应用程序提供高级cookie处理。实用程序类提供了一种检查cookie存在性、获取、设置和删除cookie的方法。功能包括

  1. 自动cookie前缀
  2. 自动cookie加密
  3. 设置cookie的有效时间相对于当前时间戳
  4. 将cookie标记为仅HTTP或安全
<?php

declare(strict_types=1);

namespace MyApp;

use ActiveCollab\Cookies\Cookies;use ActiveCollab\CurrentTimestamp\CurrentTimestamp;use ActiveCollab\Encryptor\Encryptor;

$cookies = (new Cookies(
    new CurrentTimestamp(),
    new Encryptor(),
))
    ->prefix('my_prefix_')
    ->domain('myapp.dev')
    ->secure(true)
    
if (!$cookies->exists($request, 'my_encrypted_cookie')) {
    [
        $request,
        $response,
    ] = $cookies->set(
        $request,
        $response,
        'my_encrypted_cookie', 
        'value to encrypt',
        [
            'ttl' => 3600, // One hour.
        ],
    );
}

当前时间戳

ActiveCollab\CurrentTimestamp\CurrentTimestampInterface - 接口指定了一种获取当前时间戳的方法。默认实现使用 time() 函数调用,但您可以使用任何实现,包括时间戳锁定(非常适合测试)。

加密器

ActiveCollab\Encryptor\EncryptorInterface - 接口指定了一种加密和解密值的方法。它不指定值是如何加密或解密的,只说明它们可以被加密和解密。所有依赖和实现细节都需要在实现中处理,具体配置需要通过构造函数参数或设置器来完成。默认实现使用AES 256 CBC作为包的一部分。

防火墙

ActiveCollab\Firewall\FirewallInterface - 此接口及其实现允许您将IP地址与白名单和黑名单地址列表进行比较,并阻止不想要的流量。

<?php

declare(strict_types=1);

namespace MyApp;

use ActiveCollab\Firewall\Firewall;
use ActiveCollab\Firewall\IpAddress;

$firewall = new Firewall(['72.165.1.2'], ['72.165.0.0/16']);

$firewall->shouldBlock(new IpAddress('72.165.1.2')); // No, address is white-listed.
$firewall->shouldBlock(new IpAddress('72.165.1.3')); // Yes, address is in the black-listed range.

JSON

ActiveCollab\Json\JsonEncoderInterface - 此接口及其实现提供了一种方式来编码JSON,就像我们通常做的那样,并在测试中检查数据是否被编码。

<?php

declare(strict_types=1);

use ActiveCollab\Json\JsonEncoder;

print (new JsonEncoder())->encode(
    [
        'a' => 1,
        'b' => 2,
    ],
    true,
);

电话号码

通过封装libphonenumber来提供电话号码值对象。

<?php

declare(strict_types=1);

namespace MyApp;

use ActiveCollab\PhoneNumber\Factory\PhoneNumberFactory;
use libphonenumber\PhoneNumberUtil;

$phoneNumber = (new PhoneNumberFactory(PhoneNumberUtil::getInstance()))->create('+1 800 444 4444');
print $phoneNumber-getNationalPhoneNumber() . "\n";

值容器

ActiveCollab\ValueContainer\ValueContainerInterface - 接口,它使得值访问抽象成为可能。例如,它可以用来以类不知道值存储在哪里和如何存储的方式访问值,它只知道它可以检查值的存在、获取值、设置值或删除值。

包包括ActiveCollab\ValueContainer\Request\RequestValueContainerInterface。当您有一个包含值的属性的PSR-7请求时,可以使用此接口。默认实现(包含在包中)可以读取和写入请求。

<?php

declare(strict_types=1);

namespace MyApp;

use ActiveCollab\ValueContainer\Request\RequestValueContainer;
use Psr\Http\Message\ServerRequestInterface;

/** @var ServerRequestInterface $request */
$request = $request->withAttribute('value_that_we_need', [1, 2, 3]);

$value_container = (new RequestValueContainer('value_that_we_need'))
    ->setRequest($request);

print_r($value_container->getValue()); // Prints array.

URL

ActiveCollab\Url\UrlInterface - 在当前形式下,此接口的实现允许您轻松地向已知URL添加和删除查询参数。

<?php

declare(strict_types=1);

namespace MyApp;

use ActiveCollab\Url\Url;

print (new Url('https://activecollab.com'))->getExtendedUrl(
    [
        'utm_source' => 'activecollab',
        'utm_medium' => 'website',
        'utm_campaign' => 'footer',
    ],
);

如何添加实用工具

  1. composer.json中的autoload -> psr-4下添加自动加载代码。
  2. 使用composer update更新依赖项。
  3. 实现并测试您的实用工具类。
  4. 标记并发布新版本。