vinogradsoft/compass

用于处理地址的库。支持磁盘文件路径和URL。

1.1.0 2023-12-03 01:35 UTC

This package is auto-updated.

Last update: 2024-09-04 18:21:45 UTC


README

Compass logo



创建可重用的应用程序。
开源库。

codecov

Compass 是什么?

👉 Compass 是一个用于处理 URL 和硬盘文件路径的库。它包括简化数据操作的工具。该库的目标是便于处理 URL 和文件位置上的数据。

一般信息

Compass 可以用于各种 PHP 应用程序中处理文件路径和 URL。它包括两个主要组件:Compass\PathCompass\Url。这两个组件都是独立的对象,提供了一组简单数据操作的方法。Compass\Path 提供用于处理目录的工具,包括在路径字符串中查找、替换和检查目录,以及更改它们的顺序。反过来,Compass\Url 提供用于处理 URL 的功能,允许您创建、检索和修改 URL 的各个部分。

这两个组件都遵循相似的原则,首先收集必要的参数,然后使用特殊的 updateSource() 方法将这些参数应用于结果。

安装

使用 composer 安装

php composer require vinogradsoft/compass "^1.0"

需要 PHP 8.0 或更高版本。

URL 组件

🚀 快速入门

<?php
require_once dirname(__DIR__, 1) . '/vendor/autoload.php';
use \Compass\Url;

$url = Url::createBlank();

$url->setScheme('http')->setUser('grigor')->setPassword('password')->setHost('vinograd.soft')
    ->setPort('8080')->setPath('/path/to/resource')->setSuffix('.json')
    ->setArrayQuery(['query' => 'value',])->setFragment('fragment');

$url->updateSource();

echo '<br><br><b>Authority:</b> ', $url->getAuthority();
echo '<br><b>Base Url:</b> ', $url->getBaseUrl();
echo '<br><b>Relative Url:</b> ', $url->getRelativeUrl();
echo '<br><b>Absolute Url:</b> ', $url->getSource(), '<br>';
echo '<br><b>Scheme:</b> ', $url->getScheme();
echo '<br><b>User:</b> ', $url->getUser();
echo '<br><b>Password:</b> ', $url->getPassword();
echo '<br><b>Host:</b> ', $url->getHost();
echo '<br><b>Port:</b> ', $url->getPort();
echo '<br><b>Path:</b> ', $url->getPath();
echo '<br><b>Suffix:</b> ', $url->getSuffix();
echo '<br><b>Query:</b> ', $url->getQuery();
echo '<br><b>Fragment:</b> ', $url->getFragment();

$url->setSource('http://россия.рф');
$url->setConversionIdnToAscii(true)->updateSource();
echo '<br><br><b>new URL:</b> ',$url; #http://xn--h1alffa9f.xn--p1ai

创建 Compass\Url 类的实例

Compass\Url 类可以通过调用静态方法 createBlank() 或使用 new 操作符来实例化。createBlank() 方法以其使用自己的原型进行克隆而著称。该方法有两个可选参数:$isIdnToAscii$updateStrategy,用于确定是否应将主机转换为 punycode 以及使用哪种 URL 更新策略。

第一个参数,$isIdnToAscii,确定是否应转换主机。如果设置为 true,则转换主机;如果为 false,则不转换主机。

第二个参数,$updateStrategy,确定 URL 更新策略。该策略涉及创建 URL 各个组件的方法。

要使用 new 操作符创建 Compass\Url 类的新实例,必须传递一个必需参数 - 作为字符串的原生 URL。

生成 URL 的方法

可以使用以下方法设置参数:

  • 构造函数
  • setSource 方法
  • setAll 方法
  • 特定于 URL 某个部分的特定方法(如快速入门中所示)。

⚡ 示例

👉 通过构造函数

$url = new Url('http://grigor:password@vinograd.soft:8080/path/to/resource?query=value#fragment');

👉 使用 setSource 方法

$url->setSource('http://grigor:password@vinograd.soft:8080/path/to/resource?query=value#fragment');

👉 使用 setAll 方法

$url->setAll([
    ':host' => 'host.ru',
    ':scheme' => 'http',
    ':user' => 'user',
    ':password' => 'password',
    ':port' => '80',
    ':path' => ['path', 'to', 'resource'],
    '?' => ['key' => 'value', 'key2' => 'value2'],
    '#' => 'fragment',
    ':suffix' => '.json',
]);

👉 使用负责特定 URL 部分的特定方法。

$url->setScheme('http')->setUser('grigor')->setPassword('password')->setHost('vinograd.soft')
    ->setPort('8080')->setPath('/path/to/resource')->setSuffix('.json')
    ->setArrayQuery(['query' => 'value',])->setFragment('fragment');

在前两种情况下,后缀不被识别。在这种情况下,必须使用单独的 $url->setSuffix(.json); 方法设置后缀,这是唯一可以管理它的方法。

❗ 后缀不会被解析,因为它可以是任何字符串,并且不必以点开头。如果传递带有后缀的 URL,则后缀成为 path 的一部分。

应用更改

为了使更改的参数生效,您必须调用 $url->updateSource() 方法。此方法有两个可选参数 - $updateAbsoluteUrl$suffix$updateAbsoluteUrl 参数的值决定了是否更新整个 URL 或仅更新其相对部分。默认值为 true,也就是说,默认情况下将尝试更新整个 URL。$suffix 参数的类型为 string,允许您在更新时设置后缀。

参数应用后,您可以使用 $url->getSource() 方法获取更新后的结果。

升级策略

📢 更新策略是一个对象,它结合所有输入来创建一个最终的 URL。此对象必须是 Compass\UrlStrategy 接口的实现。在系统中,执行此功能的类称为 Compass\DefaultUrlStrategy

策略是为了控制 URL 创建过程而发明的。它包含一系列方法,每个方法对应于 URL 的一个部分,其中参数被连接。哪些方法将参与更新,由 Compass\Url 对象根据各部分的状态确定。有一些标志表示哪些区域需要重新创建。为了便于理解,我们可以将此与分成若干部分“A”、“B”、“C”、“D”的公路和负责该公路的道路公司进行类比。理想情况下,公路应该始终保持平坦。当公路的一部分,例如"C",损坏时,维修团队就会去该部分进行维修。您也可以想象一个 URL,其中公路是一串具有逻辑部分(部分)的字符串。维修团队是更新策略中的方法。道路公司是 Compass\Url 对象。

策略有六个方法用于创建 URL 的部分

  • updateAuthority()
  • updateBaseUrl()
  • updateQuery()
  • updatePath()
  • updateRelativeUrl()
  • updateAbsoluteUrl().

通过为 URL 设置任何参数,系统会更改该部分的状态,就像损坏了传递参数的该部分一样。在调用 $url->updateSource(); 方法后,适当的策略方法将包含在操作中。

❗ 重要的一点是要记住,Compass\Url 对象存储了用户安装的初始部分和每个策略方法的输出结果。

方法的实现可以分为三个级别。

                                               LEVEL 3
        |--------------------------------updateAbsoluteUrl()---------------------------------|
        |                                                                                    |
        |                                      LEVEL 2                                       |
        |---------------updateBaseUrl()-----------|------------updateRelativeUrl()-----------|
        |                                         |                                          |
        |                                      LEVEL 1                                       |
        |                updateAuthority()        |     updatePath()     updateQuery()       |
        |       /‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾\|/‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾\ /‾‾‾‾‾‾‾‾\         |
        |http://grigor:password@vinograd.soft:8080/path/to/resource.json?query=value#fragment|

第三级方法 updateAbsoluteUrl() 总是执行;它组合了第二级方法的保存结果。第二级方法 updateBaseUrl()updateRelativeUrl() 组合了第一级的结果。在第一级,updateAuthority()updatePath()updateQuery() 在各自的范围内将原始部分粘合在一起。

状态操作

状态存储在 Compass\Url 类的几个字段中:$authoritySate$relativeUrlState$schemeState$authoritySate$relativeUrlState 的类型为 int$schemeState 的类型为 bool$authoritySate$relativeUrlState 的状态由位操作控制。下面是一个代码示例,显示了状态完好时的默认值

const USER_STATE = 1 << 0;
const PASSWORD_STATE = 1 << 1;
const HOST_STATE = 1 << 2;
const PORT_STATE = 1 << 3;

const PATH_STATE = 1 << 0;
const QUERY_STATE = 1 << 1;
const FRAGMENT_STATE = 1 << 2;

const AUTHORITY_WHOLE = self::USER_STATE | self::PASSWORD_STATE | self::HOST_STATE | self::PORT_STATE;
const RELATIVE_URL_WHOLE = self::PATH_STATE | self::QUERY_STATE | self::FRAGMENT_STATE;

/**
 * current states
 */
protected int $authoritySate = self::AUTHORITY_WHOLE;
protected int $relativeUrlState = self::RELATIVE_URL_WHOLE;
protected bool $schemeState = true;

如果我们想损坏 $relativeUrlStatequery 区域的状态,我们可以使用位运算符

$relativeUrlState &= ~Url::QUERY_STATE;

其余部分可以以类似的方式进行操作,除了 $schemeState,它需要分配一个布尔值。

⚡ 创建您自己的策略示例

在构建您的 URL 更新过程时,有时您希望执行一个方法,该方法基于当前状态将不会执行。在这种情况下,使用额外的 forceUnlockMethod(...) 方法,您可以在某些部分中更改当前状态,从而强制系统执行所需的方法。

通过例子可以更好地理解这一点。让我们想象我们需要生成推广链接的URL。让我们制定一个策略,为所有具有another.site域的URL添加一个等于40refid参数。

策略代码

<?php

namespace <your\namespace>;

use Compass\DefaultUrlStrategy;
use Compass\Url;

class ReferralUrlStrategy extends DefaultUrlStrategy
{

    private bool $isAllowInsertParam = false;

    /**
     * @inheritDoc
     */
    public function updateQuery(array $items): string
    {
        if ($this->isAllowInsertParam) {
            $items['refid'] = 40;
            $this->isAllowInsertParam = false;
        }
        return http_build_query($items, '', '&', PHP_QUERY_RFC3986);
    }

    /**
     * @inheritDoc
     */
    public function forceUnlockMethod(
        bool    &$schemeState,
        int     &$authoritySate,
        int     &$relativeUrlState,
        array   $items,
        array   $pathItems,
        array   $queryItems,
        bool    $updateAbsoluteUrl,
        ?string $suffix = null
    ): void
    {
        if ($items[Url::HOST] === 'another.site') {
            $this->isAllowInsertParam = true;
        }
        $relativeUrlState &= ~Url::QUERY_STATE;
    }

}

现在让我们设置策略并输出两个URL,其中一个将是目的地,域名是another.site

$url = Url::createBlank();
$url->setUpdateStrategy(new ReferralUrlStrategy());

$url->setSource('https://another.site');
$url->updateSource();
echo $url->getSource(), '<br>'; # https://another.site/?refid=40

$url->setHost('vinograd.soft');
$url->updateSource();
echo $url->getSource(); # https://vinograd.soft

乍一看,似乎状态改变($relativeUrlState &= ~Url::QUERY_STATE;)应该写在if结构中,但这并不正确。在我们安装了vinograd.soft主机后,调用updateSource()方法不会导致我们的策略的updateQuery方法的执行,因为没有添加任何参数以常规方式改变此部分的状态。因此,状态将保持不变,只有baseurl部分将被更新,并且上次保存的refid=40参数将与包含vinograd.soft主机的新的baseurl合并。

此示例表明,您不仅限于设置URL部分的常规方法。使用策略,您可以后处理结果,例如,当您需要为包含URL的HTML属性(href、src以及其他此类属性)转义结果时。

路径组件

👉 Compass\Path可以描述为文件路径的对象表示。它在不依赖实际文件系统的情况下操作路径字符串。该组件,如Compass\Url,有一个更新策略,包括一个updatePath()方法。重要的是要注意,该组件是无状态的。

🚀方法演示

<?php

use Compass\Path;

require_once dirname(__DIR__, 1) . '/vendor/autoload.php';

$path = new Path('/__NAME__/__NAME__Scanner/__NAME2__Driver', '/');

$path->replaceAll([
    '__NAME__' => 'User',
    '__NAME2__' => 'Filesystem',
]);
$path->updateSource();

echo '<br>', $path; # /User/UserScanner/FilesystemDriver

$path->setAll(['path', 'to', 'file.txt']);
$path->updateSource();

echo '<br>', $path; # path/to/file.txt

$path->set(1, 'newTo');
$path->updateSource();

echo '<br>', $path; # path/newTo/file.txt

$path->setBy('path', 'newPath');
$path->updateSource();

echo '<br>', $path; # newPath/newTo/file.txt

echo '<br>', $path->dirname(); # newPath/newTo

$path->setSuffix('.v');
$path->updateSource();
echo '<br>', $path; # newPath/newTo/file.txt.v

$path->setSource('newPath/newTo/file');
$path->setSuffix('.v');
$path->updateSource();
echo '<br>', $path; # newPath/newTo/file.v

$path->replace('newPath','path');
$path->updateSource();
echo '<br>', $path; # path/newTo/file.v
echo '<br>', $path->getLast(); # file.v

测试

php composer测试

贡献

有关详细信息,请参阅贡献指南

许可

MIT许可(MIT)。有关更多信息,请参阅许可文件