symplify/phpstan-rules

一套用于 PHPStan 的 Symplify 规则

安装量: 4,328,923

依赖者: 160

建议者: 2

安全: 0

星星: 149

关注者: 5

分支: 23

开放性问题: 0

类型:phpstan-extension

13.0.1 2024-08-23 09:02 UTC

This package is auto-updated.

Last update: 2024-09-16 20:28:44 UTC


README

Downloads

用于 Symplify 项目的 PHPStan 规则集


安装

composer require symplify/phpstan-rules --dev

注意:请确保使用 phpstan/extension-installer 加载必要的服务配置。


1. 添加准备好的规则集

规则集是一组按共同区域分组(例如改进命名)的规则。您可以从中选择 5 个规则集。

includes:
    - vendor/symplify/phpstan-rules/config/code-complexity-rules.neon
    - vendor/symplify/phpstan-rules/config/naming-rules.neon
    - vendor/symplify/phpstan-rules/config/regex-rules.neon
    - vendor/symplify/phpstan-rules/config/static-rules.neon

逐个添加规则集,修复您认为有用的,忽略其余部分。


您是否编写自定义 Rector 规则?也为它们添加规则。

includes:
    - vendor/symplify/phpstan-rules/config/rector-rules.neon

2. 挑选可配置的规则

有一个包含预配置的可配置规则的规则集。包含它并查看发现了哪些错误

# phpstan.neon
includes:
    - vendor/symplify/phpstan-rules/config/configurable-rules.neon

您想 根据您的口味定制它 吗?选择一个 PHPStan 规则并手动配置它 ↓

services:
    -
        class: Symplify\PHPStanRules\Rules\ForbiddenNodeRule
        tags: [phpstan.rules.rule]
        arguments:
            forbiddenNodes:
                - PhpParser\Node\Expr\Empty_
                - PhpParser\Node\Stmt\Switch_

3. 注册特定规则


30 规则概览

AnnotateRegexClassConstWithRegexLinkRule

添加一个链接到 regex101.com,显示实际的正则表达式,以便在将来出现错误/扩展时更容易维护

class SomeClass
{
    private const COMPLICATED_REGEX = '#some_complicated_stu|ff#';
}


class SomeClass
{
    /**
     * @see https://regex101.com/r/SZr0X5/12
     */
    private const COMPLICATED_REGEX = '#some_complicated_stu|ff#';
}

👍


CheckClassNamespaceFollowPsr4Rule

类命名空间 "%s" 不遵循 composer.json 中的 PSR-4 配置

// defined "Foo\Bar" namespace in composer.json > autoload > psr-4
namespace Foo;

class Baz
{
}


// defined "Foo\Bar" namespace in composer.json > autoload > psr-4
namespace Foo\Bar;

class Baz
{
}

👍


CheckRequiredInterfaceInContractNamespaceRule

接口必须位于 "Contract" 或 "Contracts" 命名空间

namespace App\Repository;

interface ProductRepositoryInterface
{
}


namespace App\Contract\Repository;

interface ProductRepositoryInterface
{
}

👍


ClassNameRespectsParentSuffixRule

类应该有后缀 "%s" 以尊重父类型

🔧 配置它!

services:
    -
        class: Symplify\PHPStanRules\Rules\ClassNameRespectsParentSuffixRule
        tags: [phpstan.rules.rule]
        arguments:
            parentClasses:
                - Symfony\Component\Console\Command\Command

class Some extends Command
{
}


class SomeCommand extends Command
{
}

👍


ExplicitClassPrefixSuffixRule

接口后缀为 "Interface",trait 后缀为 "Trait" 独占

<?php

interface NotSuffixed
{
}

trait NotSuffixed
{
}

abstract class NotPrefixedClass
{
}


<?php

interface SuffixedInterface
{
}

trait SuffixedTrait
{
}

abstract class AbstractClass
{
}

👍


ForbiddenArrayMethodCallRule

不允许使用数组方法调用 [$this, "method"]。使用显式方法代替以帮助 PhpStorm、PHPStan 和 Rector 理解您的代码

usort($items, [$this, "method"]);


usort($items, function (array $apples) {
    return $this->method($apples);
};

👍


ForbiddenExtendOfNonAbstractClassRule

只能扩展抽象类

final class SomeClass extends ParentClass
{
}

class ParentClass
{
}


final class SomeClass extends ParentClass
{
}

abstract class ParentClass
{
}

👍


ForbiddenFuncCallRule

函数 "%s()" 不能在代码中使用/保留

🔧 配置它!

services:
    -
        class: Symplify\PHPStanRules\Rules\ForbiddenFuncCallRule
        tags: [phpstan.rules.rule]
        arguments:
            forbiddenFunctions:
                - eval

echo eval('...');


echo '...';

👍


services:
    -
        class: Symplify\PHPStanRules\Rules\ForbiddenFuncCallRule
        tags: [phpstan.rules.rule]
        arguments:
            forbiddenFunctions:
                dump: 'seems you missed some debugging function'

dump($value);
echo $value;


echo $value;

👍


禁止在一个文件中定义多个类

单个文件中不允许定义多个类/接口/特质

// src/SomeClass.php
class SomeClass
{
}

interface SomeInterface
{
}


// src/SomeClass.php
class SomeClass
{
}

// src/SomeInterface.php
interface SomeInterface
{
}

👍


禁止使用节点规则

"%s" 被禁止使用

🔧 配置它!

services:
    -
        class: Symplify\PHPStanRules\Rules\ForbiddenNodeRule
        tags: [phpstan.rules.rule]
        arguments:
            forbiddenNodes:
                - PhpParser\Node\Expr\ErrorSuppress

return @strlen('...');


return strlen('...');

👍


禁止静态类常量获取规则

避免静态访问常量,因为它们可能会改变值。使用接口和契约方法代替

class SomeClass
{
    public function run()
    {
        return static::SOME_CONST;
    }
}


class SomeClass
{
    public function run()
    {
        return self::SOME_CONST;
    }
}

👍


不允许动态名称规则

使用显式名称而不是动态名称

class SomeClass
{
    public function old(): bool
    {
        return $this->${variable};
    }
}


class SomeClass
{
    public function old(): bool
    {
        return $this->specificMethodName();
    }
}

👍


不允许实体在实体命名空间外

带有 #[Entity] 属性的类必须位于 "Entity" 命名空间中,以便 Doctrine 加载

namespace App\ValueObject;

use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class Product
{
}


namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class Product
{
}

👍


不允许全局常量规则

全局常量被禁止。使用类似枚举的类列表代替

const SOME_GLOBAL_CONST = 'value';


class SomeClass
{
    public function run()
    {
        return self::SOME_CONST;
    }
}

👍


不允许内联字符串正则表达式规则

使用本地命名常量而不是内联字符串作为正则表达式,通过常量名称解释含义

class SomeClass
{
    public function run($value)
    {
        return preg_match('#some_stu|ff#', $value);
    }
}


class SomeClass
{
    /**
     * @var string
     */
    public const SOME_STUFF_REGEX = '#some_stu|ff#';

    public function run($value)
    {
        return preg_match(self::SOME_STUFF_REGEX, $value);
    }
}

👍


不允许引用规则

使用显式返回值而不是魔法引用

class SomeClass
{
    public function run(&$value)
    {
    }
}


class SomeClass
{
    public function run($value)
    {
        return $value;
    }
}

👍


不允许返回数组变量列表规则

使用值对象而不是返回值

class ReturnVariables
{
    public function run($value, $value2): array
    {
        return [$value, $value2];
    }
}


final class ReturnVariables
{
    public function run($value, $value2): ValueObject
    {
        return new ValueObject($value, $value2);
    }
}

👍


不允许返回设置器方法规则

设置器方法不能返回任何内容,只能设置值

final class SomeClass
{
    private $name;

    public function setName(string $name): int
    {
        return 1000;
    }
}


final class SomeClass
{
    private $name;

    public function setName(string $name): void
    {
        $this->name = $name;
    }
}

👍


不允许单接口实现者规则

接口 "%s" 只有一个实现者。考虑直接使用类,因为使用接口没有意义。

class SomeClass implements SomeInterface
{
}

interface SomeInterface
{
}


class SomeClass implements SomeInterface
{
}

class AnotherClass implements SomeInterface
{
}

interface SomeInterface
{
}

👍


不允许测试模拟规则

禁止模拟 "%s" 类。为了更好的静态分析,使用直接/匿名类代替

use PHPUnit\Framework\TestCase;

final class SkipApiMock extends TestCase
{
    public function test()
    {
        $someTypeMock = $this->createMock(SomeType::class);
    }
}


use PHPUnit\Framework\TestCase;

final class SkipApiMock extends TestCase
{
    public function test()
    {
        $someTypeMock = new class() implements SomeType {};
    }
}

👍


首选类规则

使用 "%s" 类/接口而不是 "%s"

🔧 配置它!

services:
    -
        class: Symplify\PHPStanRules\Rules\PreferredClassRule
        tags: [phpstan.rules.rule]
        arguments:
            oldToPreferredClasses:
                SplFileInfo: CustomFileInfo

class SomeClass
{
    public function run()
    {
        return new SplFileInfo('...');
    }
}


class SomeClass
{
    public function run()
    {
        return new CustomFileInfo('...');
    }
}

👍


防止父方法可见性覆盖规则

"%s()" 方法的可见性更改为 "%s",以尊重父方法的可见性。

class SomeParentClass
{
    public function run()
    {
    }
}

class SomeClass extends SomeParentClass
{
    protected function run()
    {
    }
}


class SomeParentClass
{
    public function run()
    {
    }
}

class SomeClass extends SomeParentClass
{
    public function run()
    {
    }
}

👍


正则常量后缀规则

使用 "_REGEX" 后缀命名常量,而不是 "%s"

class SomeClass
{
    public const SOME_NAME = '#some\s+name#';

    public function run($value)
    {
        $somePath = preg_match(self::SOME_NAME, $value);
    }
}


class SomeClass
{
    public const SOME_NAME_REGEX = '#some\s+name#';

    public function run($value)
    {
        $somePath = preg_match(self::SOME_NAME_REGEX, $value);
    }
}

👍


RequireAttributeNameRule

属性必须显式定义所有名称

use Symfony\Component\Routing\Annotation\Route;

class SomeController
{
    #[Route("/path")]
    public function someAction()
    {
    }
}


use Symfony\Component\Routing\Annotation\Route;

class SomeController
{
    #[Route(path: "/path")]
    public function someAction()
    {
    }
}

👍


RequireAttributeNamespaceRule

属性必须位于 "Attribute" 命名空间

// app/Entity/SomeAttribute.php
namespace App\Controller;

#[\Attribute]
final class SomeAttribute
{
}


// app/Attribute/SomeAttribute.php
namespace App\Attribute;

#[\Attribute]
final class SomeAttribute
{
}

👍


RequireExceptionNamespaceRule

Exception 必须位于 "Exception" 命名空间

// app/Controller/SomeException.php
namespace App\Controller;

final class SomeException extends Exception
{

}


// app/Exception/SomeException.php
namespace App\Exception;

final class SomeException extends Exception
{
}

👍


RequireInvokableControllerRule

使用具有 __invoke() 方法的可调用控制器,而不是命名动作方法

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;

final class SomeController extends AbstractController
{
    #[Route()]
    public function someMethod()
    {
    }
}


use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;

final class SomeController extends AbstractController
{
    #[Route()]
    public function __invoke()
    {
    }
}

👍


RequireUniqueEnumConstantRule

枚举常量 "%s" 重复。请使它们唯一

use MyCLabs\Enum\Enum;

class SomeClass extends Enum
{
    private const YES = 'yes';

    private const NO = 'yes';
}


use MyCLabs\Enum\Enum;

class SomeClass extends Enum
{
    private const YES = 'yes';

    private const NO = 'no';
}

👍


SeeAnnotationToTestRule

类 "%s" 缺少包含测试用例类引用的 @see 注解

🔧 配置它!

services:
    -
        class: Symplify\PHPStanRules\Rules\SeeAnnotationToTestRule
        tags: [phpstan.rules.rule]
        arguments:
            requiredSeeTypes:
                - Rule

class SomeClass extends Rule
{
}


/**
 * @see SomeClassTest
 */
class SomeClass extends Rule
{
}

👍


UppercaseConstantRule

常量 "%s" 必须为大写

final class SomeClass
{
    public const some = 'value';
}


final class SomeClass
{
    public const SOME = 'value';
}

👍



快乐编码!