New in Symplify 9: More than 110 PHPStan Rules

In Symplify 8, a bunch of PHP rules was part of the symplify/coding-standard package. It was a mix of too many tools, so we decided to decouple a new package - symplify/phpstan-rules.

During summer 2020, our Rector team grew from 1 member to 4. To keep onboarding smooth, we started to use PHPStan to help with code-reviews in Rector. We got obsessed with moving human code-reviews to CI.

Was it worth it? Hell yea!

That's how we grew from 20 rules to 110 PHPStan Rules in ~3 months. I'd say we are barely scratching the surface of what CI can handle for us in code-reviews, but 110 rules is a solid base to start from.


Since Symplify 9, released on December 9th, you can use them in your code. Give it a try:

composer require symplify/phpstan-rules --dev

This is not a typical PHPStan package you're used to. That you just install, add to phpstan.neon and forget.

symplify/phpstan-rules is more like a bucket of lego bricks. It has prepared parts that you can use, but it's up to you to configure them.


symplify/phpstan-rules has 3 main areas:

We'll take them one by one, from the simplest to most powerful.

1. Static Rules

These rules are not configurable. You either use them or not. Dare to try them all and see what happens?

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

Or do you want to cherry-pick rule by rule? Go through the rules overview with PHP code snippets and copy-paste those you like:

rules:
    - Symplify\PHPStanRules\Rules\CheckRequiredInterfaceInContractNamespaceRule

Some rules require extra services. To avoid service duplications, they're in the separate config that you can easily include:

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

That's it!

2. Prepared Sets

Special group of static rules are prepared sets. Similar to ECS sets, each has one area it focuses on:

includes:
    - vendor/symplify/phpstan-rules/config/array-rules.neon
    - vendor/symplify/phpstan-rules/config/code-complexity-rules.neon
    - vendor/symplify/phpstan-rules/config/doctrine-rules.neon
    - vendor/symplify/phpstan-rules/config/naming-rules.neon
    - vendor/symplify/phpstan-rules/config/regex-rules.neon
    - vendor/symplify/phpstan-rules/config/services-rules.neon
    - vendor/symplify/phpstan-rules/config/size-rules.neon
    - vendor/symplify/phpstan-rules/config/forbid-static-rules.neon
    - vendor/symplify/phpstan-rules/config/string-to-constant-rules.neon
    - vendor/symplify/phpstan-rules/config/symfony-rules.neon
    - vendor/symplify/phpstan-rules/config/test-rules.neon

Pick what you like and drop the rest.

3. Configurable Rules

This is the powerful part that PHPStan advanced users will appreciate.

You can tune configurable rules to your project context. Do you need more strict cognitive complexity? No problem. Do you want to allow fewer dependencies in the constructor? Just set it.

Configurable rules are configured for Symplify by defaults. You can find them in:

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

Symplify standards might not fit your standard, so it's better to use rules separately.

Example: Configuring ForbiddenNodeRule

Let's look at ForbiddenNodeRule. In this rule, you can say what nodes are forbidden to use.

We don't like switch(), empty() and @, so we forbid them:

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

Now on each CI run, PHPStan makes sure our code is clean and with high standard :)


That's it!




Do you learn from my contents or use open-souce packages like Rector every day?
Consider supporting it on GitHub Sponsors. I'd really appreciate it!