【问题标题】:What is the "Add #[Pure] attribute" inspection in PhpStorm checking for?PhpStorm 检查中的“添加#[Pure] 属性”检查是什么?
【发布时间】:2021-11-26 21:39:35
【问题描述】:

我在 Laravel 项目中有一个非常简单的 FormRequest 类。两种方法,这两种方法都返回一个由方法部分填充的简单数组,但 IDE 对它们的处理方式不同。

<?php

namespace App\Http\Requests;

class VerifyPhoneNumber extends FormRequest {
    use Support\ValidatesPhoneNumbers;

    public function authorize(): bool {
        return true;
    }

    public function rules(): array {
        return [
            "phone_number" => $this->getPhoneNumberRules(),
            "verify_code" => ["required", "numeric", "max:999999"],
        ];
    }

    public function messages(): array {
        return [
            "phone_number.regex" => $this->getPhoneNumberMessage(),
        ];
    }
}

以及非常基本的 trait 方法:

<?php

namespace App\Http\Requests\Support;

trait ValidatesPhoneNumbers {
    protected function getPhoneNumberMessage(): string {
        return __("Some localized error message");
    }

    protected function getPhoneNumberRules(): array {
        return ["regex:/^\+?1?[2-9][0-9]{5,14}$/", "max:16"];
    }
}

让我感到困惑的是,IDE 检查抱怨我应该将JetBrains\PhpStorm\Pure 属性添加到rules() 方法,而不是messages() 方法。

the class definition 中的 cmets 说:

该属性标记对程序状态或函数执行后使用的传递参数没有影响的函数。 这意味着如果执行结果没有在之后的代码中使用,则可以安全地删除解析为此类函数的函数调用。

这并没有真正给我任何线索,为什么它以不同的方式对待这两种方法。如果我对第二句话的理解正确,那么当“纯”方法的结果未使用时,IDE 会将该方法的使用标记为未使用并建议将其删除。

确定何时需要此属性的逻辑是什么?

【问题讨论】:

    标签: php phpstorm php-8


    【解决方案1】:

    如果一个函数只依赖于其他纯函数,那么它也是纯函数。由于getPhoneNumberRules()只是返回一个固定的数组,所以是纯的,所以rules()也是纯的。

    但是messages()调用getPhoneNumberMessage(),后者调用__()函数,如果位置状态发生变化,可以返回不同的本地化消息,所以不是纯的。

    【讨论】:

    • 感觉这个“纯粹”的东西对高维护是开放的。一旦方法发生更改,或者子方法或该方法使用的某个 DI 类发生更改,那么它可能不再是 Pure。
    • 它本质上是一种文档形式(它只是一种旨在供 IDE 使用而不是供人类直接使用的格式)。所以如果你改变了一个函数的行为,你需要保持它的一致性。
    【解决方案2】:

    rules() 方法具有固定(最好说“无副作用”)结果——它只使用固定值。当然,它从一个特征调用getPhoneNumberRules(),但它也返回固定数组(总是相同的)。它不会在其他任何地方(内部状态或外部存储)进行更改。

    messages() 方法从一个调用 __() 的特征中调用一个方法来获取翻译的消息...该消息可能来自不同的源(数据库、文件),因此如果存储 (文件/数据库)不可读。 IDE 不确定__() 是否对文件/数据库进行了更改——它没有被注释为纯的,PhpStorm 无法通过它使用的方法做出这样的决定。


    PS 如果此检查让您感到烦恼(我可以理解),那么我建议您忽略此类检查并将其在 PhpStorm 设置中的严重性降低为“不突出显示,仅修复”(Settings (Preferences on macOS) | Editor | Inspections | PHP | Attributes | '#[Pure]' attribute can be added

    【讨论】:

    • 不是 OP,但我在理解为什么不断变化的本地化消息使其不“纯”时遇到了一些麻烦。对__() 的调用也引起了我的兴趣,但既然它是一个只读机制,那它不是纯粹的according to the definition given by JetBrains 吗?
    • @NoahBoegli __() 读取文件(甚至是数据库)以获取翻译。如果存储(文件/数据库)不可读,此类操作可能会引发异常。当然,__() 只读取而不修改文件/数据库 .. 但 IDE 不知道它。更改 __() 并将其声明为 Pure,IDE 将为上述示例中的两种方法提供相同的功能。
    • I/O 或资源错误的好点,我也想知道一点。但是我认为更多的是 Phpstorm 不能完全完成分析,所以 only 建议 Pure 属性,它是 100% 确定它是纯的并且只是纯的。 Phpstorm 不能知道所有的库。
    • 让我们在那个错误情况下稍微弯曲一下:这是否意味着,只要 PHP 基于文件的自动加载有效,扩展、实现或使用(特征)的类的方法可以不纯洁?
    • #Pure 在 PhpStorm 中与其他语言/文献中的“纯函数”含义不完全匹配。这就是为什么您可以找到将其重命名为 #[NoSideEffect youtrack.jetbrains.com/issue/WI-56211 的建议。
    【解决方案3】:

    将此属性用于不产生任何副作用的函数。所有此类 PHP 内部函数都已在 PhpStorm 中标记。

    #[Pure]
    function compare(Foo $a, Foo $b): int
    {
        return $a->a <=> $b->b;
    }
    

    来源:https://github.com/JetBrains/phpstorm-attributes#pure

    因为这个函数只在它自己的范围内做一些事情,所以它可以被称为#[Pure] 函数,所以你可以通过 PhpStorm 知道这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-20
      • 2018-12-17
      • 2013-07-08
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多