PhpStorm 检查中的“Add #[Pure] attribute”检查是什么?

mik*_*n32 18 php phpstorm php-8

FormRequest我在 Laravel 项目中有一个非常简单的类。两种方法,两者都返回一个由方法部分填充的简单数组,但 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(),
        ];
    }
}
Run Code Online (Sandbox Code Playgroud)

以及非常基本的特征方法:

<?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"];
    }
}
Run Code Online (Sandbox Code Playgroud)

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

类定义中的注释说:

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

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

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

Laz*_*One 13

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

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


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

  • 不是OP,但我很难理解为什么不断变化的本地化消息使它不“纯粹”。对 __() 的调用也引起了我的兴趣,但由于它是一种只读机制,这不会使它变得纯粹[根据 JetBrains 给出的定义](https://blog.jetbrains.com/phpstorm/2020 /10/phpstorm-2020-3-eap-4/#pure)? (2认同)

Bar*_*mar 6

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

但是messages()调用getPhoneNumberMessage(),它调用的__()函数可以在位置状态发生变化时返回不同的本地化消息,因此它不是纯粹的。