跳至正文

静态分析

为了帮助使用此库对代码库进行静态分析,提供了 [PHPStan] 扩展和 [Psalm] 插件。它们使这些工具能够更好地理解映射器的行为。

注意

要激活此功能,必须正确注册插件:

phpstan.neon
includes:
    - vendor/cuyz/valinor/qa/PHPStan/valinor-phpstan-configuration.php
作曲家.json
"autoload-dev": {
    "files": [
        "vendor/cuyz/valinor/qa/Psalm/ValinorPsalmPlugin.php"
    ]
}
诗篇.xml
<plugins>
    <pluginClass class="CuyZ\Valinor\QA\Psalm\ValinorPsalmPlugin"/>
</plugins>

考虑到项目中至少安装了其中一个工具,下面是将报告的错误类型的示例。

映射到类数组

final readonly class SomeClass
{
    public function __construct(
        public string $foo,
        public int $bar,
    ) {}
}

$objects = (new \CuyZ\Valinor\MapperBuilder())
    ->mapper()
    ->map(
        'array<' . SomeClass::class . '>',
        [/* … */]
    );

foreach ($objects as $object) {
    // ✅
    echo $object->foo;

    // ✅
    echo $object->bar * 2;

    // ❌ Cannot perform operation between `string` and `int`
    echo $object->foo * $object->bar;

    // ❌ Property `SomeClass::$fiz` is not defined
    echo $object->fiz;
}

映射到指定结构的数组

$array = (new \CuyZ\Valinor\MapperBuilder())
    ->mapper()
    ->map(
        'array{foo: string, bar: int}',
        [/* … */]
    );

// ✅
echo $array['foo'];

// ❌ Expected `string` but got `int`
echo strtolower($array['bar']);

// ❌ Cannot perform operation between `string` and `int`
echo $array['foo'] * $array['bar'];

// ❌ Offset `fiz` does not exist on array
echo $array['fiz']; 

映射可调用对象的参数

$someFunction = function(string $foo, int $bar): string {
    return "$foo / $bar";
};

$arguments = (new \CuyZ\Valinor\MapperBuilder())
    ->argumentsMapper()
    ->mapArguments($someFunction, [
        'foo' => 'some value',
        'bar' => 42,
    ]);

// ✅ Arguments have a correct shape, no error reported
echo $someFunction(...$arguments);

关于映射器和规范化器纯度

映射器和规范化器被设计为纯粹的,这意味着它们没有副作用,并且对于相同的输入始终返回相同的结果。有关更多信息,请参阅纯函数的定义。

建议在开发应用程序时通过使用 [PHPStan] 和 [Psalm] 处理的@pure注释来牢记纯度。

映射用户提供的数据本身就是一个潜在危险的操作:通过仅依赖纯函数/类型进行映射,可以确保恶意用户输入在调用TreeMapper::map()时不会造成副作用。您可以自由地抑制/忽略给定的纯度准则,但代价是扩大攻击面。

在某些情况下,纯度分析可能会返回误报,这些误报很容易被忽略,例如通过使用@phpstan-ignore和@psalm-suppress注释。

注意

如果报告了太多有关映射器或规范化器的纯度错误,则此库提供了一种全局忽略它们的方法:

phpstan.neon
includes:
    - vendor/cuyz/valinor/qa/PHPStan/valinor-phpstan-suppress-pure-errors.php
诗篇.xml
<xi:include href="vendor/cuyz/valinor/qa/Psalm/valinor-psalm-suppress-pure-errors.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>