Skip to content

iwf-web/phpstan-rules

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

IWF PHPStan Rules

Custom PHPStan rules used across IWF projects to enforce coding standards, security practices, and architectural conventions.

License Version Version (including pre-releases) Downloads on Packagist Coverage

Requirements

  • PHP 8.3 or higher
  • PHPStan ^2.1

Installation

composer require --dev iwf-web/phpstan-rules

Usage

Include the rule set in your phpstan.neon or phpstan.neon.dist:

includes:
    - vendor/iwf-web/phpstan-rules/rules.neon

Configuration

Several rules require or accept configuration parameters under the iwf key.

Controller rules

parameters:
    iwfWeb:
        controller:
            controllerNamespace: 'App\Controller'
            excludedNamespaces: []
            excludedControllers:
                - 'App\Controller\Api\Security\LoginController'

Required use aliases

Enforce that specific namespaces are always imported with a defined alias:

parameters:
    iwfWeb:
        requiredUseAlias:
            aliasDefinitions:
                - { namespace: 'Doctrine\ORM\Mapping', alias: 'ORM' }
                - { namespace: 'Symfony\Component\Validator\Constraints', alias: 'Assert' }

Attribute requirements

Enforce that certain attributes may only appear alongside required companion attributes:

parameters:
    iwfWeb:
        attributeRequirements:
            attributeDefinitions:
                -
                    attribute: 'Symfony\Component\Routing\Attribute\Route'
                    requires:
                        - 'OpenApi\Attributes\Tag'
                        - 'Symfony\Component\Security\Http\Attribute\IsGranted'

Force DateProvider (requires coala/date-provider-bundle)

parameters:
    iwfWeb:
        forceDateProvider:
            allowedFormats:
                - 'Y-m-d'
                - 'Y-m-d H:i:s'
                - 'Y-m-d\TH:i:s'
                - 'Y-m-d\TH:i:sP'
                - 'U'

Handle-bus traits (requires coala/messenger-bundle)

parameters:
    iwfWeb:
        handleBusTrait:
            handleBusTraitMappings:
                queryBus: 'Coala\MessengerBundle\Messenger\HandleQueryBusTrait'
            handleBusTraitNamespaces:
                - 'App\Controller'

Require invalid-data-test group (requires coala/testing-bundle)

parameters:
    iwfWeb:
        requireInvalidDataTestGroup:
            requireInvalidDataTestGroupNamespaces:
                - 'App\Tests'

Rules

Common

iwfWeb.mbFunctionUsageRule — Multibyte function usage

Flags calls to string functions that have a multibyte-safe counterpart and may produce incorrect results when the input contains multibyte characters (e.g. UTF-8).

Affected functions: chr, ord, parse_str, str_pad, str_split, stripos, stristr, strlen, strpos, strrchr, strripos, strrpos, strstr, strtolower, strtoupper, substr, substr_count.

// ❌ flagged
$len = strlen($userInput);

// ✅ correct
$len = mb_strlen($userInput);

iwfWeb.noAnnotationAsAttribute — No legacy Symfony annotation namespaces

Prevents using classes from the legacy Symfony\...\Annotation\ namespace as PHP 8 attributes. Symfony has migrated all annotations to Symfony\...\Attribute\.

// ❌ flagged
#[Symfony\Component\Routing\Annotation\Route('/foo')]

// ✅ correct
#[Symfony\Component\Routing\Attribute\Route('/foo')]

iwfWeb.requiredUseAlias — Required import aliases

Enforces that configured namespaces are always imported under a specific alias. Applies to both regular use statements and group use statements.

// ❌ flagged — missing alias
use Doctrine\ORM\Mapping;

// ✅ correct
use Doctrine\ORM\Mapping as ORM;

iwfWeb.attributeRequirements — Attribute companion requirements

Ensures that when a trigger attribute is present on a method, all configured companion attributes are also present.

// ❌ flagged — #[Route] without #[IsGranted]
#[Route('/admin/users')]
public function list(): object { ... }

// ✅ correct
#[Route('/admin/users')]
#[IsGranted('ROLE_ADMIN')]
public function list(): object { ... }

Controller

iwfWeb.controllerHandleReturnType — Controller handle() return type

In controllers that use Symfony's HandleTrait, actions returning $this->handle(...) must declare their return type as object (or mixed). A more specific type causes a TypeError when the message bus returns an unexpected response such as an ErrorResponse.

// ❌ flagged — too specific, will TypeError on error responses
public function __invoke(Request $request): RecordsResponse
{
    return $this->handle(new GetRecordsQuery());
}

// ✅ correct
public function __invoke(Request $request): object
{
    return $this->handle(new GetRecordsQuery());
}

iwfWeb.controllerMissingIsGranted — Controller missing #[IsGranted]

Every public controller method carrying a #[Route] attribute must also carry a #[IsGranted] attribute — either on the method itself or on the class. Excludes abstract classes and any configured namespaces or class names.

// ❌ flagged
#[Route('/api/users')]
public function index(): object { ... }

// ✅ correct
#[Route('/api/users')]
#[IsGranted('ROLE_USER')]
public function index(): object { ... }

Coala — DateProvider

These rules are only active when Coala\DateProviderBundle is present in the project.

iwfWeb.forceDateProviderNew / iwfWeb.forceDateProviderFuncCall / iwfWeb.forceDateProviderStaticCall

Disallows creating DateTime/DateTimeImmutable without an absolute date string argument, calling time-sensitive functions (time(), date(), etc.), or using static factory methods that produce the current time. Enforces the use of DateProviderInterface instead, which enables deterministic time in tests.

// ❌ flagged
$now = new DateTimeImmutable();
$ts  = time();

// ✅ correct
$now = $this->dateProvider->now();

Coala — Messenger

This rule is only active when Coala\MessengerBundle is present in the project.

iwfWeb.useHandleBusTrait

In configured namespaces, if a class defines a setter method that corresponds to a configured handle-bus trait (e.g. setQueryBus()), it must use the matching trait instead of defining the setter manually.


Coala — Testing

This rule is only active when Coala\TestingBundle is present in the project.

iwfWeb.requireInvalidDataTestGroup

Test methods that call assertFailingValidation() must carry #[Group('invalid-data-test')]. This allows the test suite to run invalid-data tests in isolation.

// ❌ flagged
public function testInvalidEmail(): void
{
    $this->assertFailingValidation(...);
}

// ✅ correct
#[Group('invalid-data-test')]
public function testInvalidEmail(): void
{
    $this->assertFailingValidation(...);
}

Development

Prerequisites

  • Docker with Compose

Bootstrap

After cloning the repository, run the install script to set up the vendor directory and extract PHPStan source files for IDE indexing:

bin/install.sh

This is equivalent to running composer install — the PHPStan extraction is triggered automatically as a post-install hook and requires no additional IDE configuration.

Running tests

bin/test.sh

Runs PHPStan and PHPUnit against all configured Docker services sequentially.

To target a specific PHP version:

bin/test.sh 8.3

Linting

bin/lint.sh

Runs PHP CS Fixer and applies fixes in place. To check without modifying files (as CI does), run:

composer lint:check

Running Composer commands

bin/composer.sh <args>

Runs Composer inside the default Docker container. Examples:

bin/composer.sh install
bin/composer.sh require --dev some/package

Debugging with Xdebug

Xdebug is included in the local Docker images and configured with start_with_request=trigger. To activate it, set the XDEBUG_TRIGGER environment variable:

XDEBUG_TRIGGER=1 bin/test.sh

Or configure your IDE to listen on port 9003 and set XDEBUG_TRIGGER=1 in the Docker run environment.


Contributing

Please read CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.

This project uses Conventional Commits for automated releases and changelog generation.

Versioning

We use SemVer for versioning. For available versions, see the tags on this repository.

Authors

Special thanks for all the people who had helped this project so far

See also the full list of contributors who participated in this project.

I would like to join this list. How can I help the project?

We're currently looking for contributions for the following:

  • Bug fixes
  • Translations
  • etc...

For more information, please refer to our CONTRIBUTING.md guide.

License

This project is licensed under the MIT License - see the LICENSE.txt file for details.

Acknowledgments

This project currently uses no third-party libraries or copied code.

About

Custom rules for PHPStan for applications developed by IWF

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors