PHPackages                             iwf-web/phpstan-rules - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Validation &amp; Sanitization](/categories/validation)
4. /
5. iwf-web/phpstan-rules

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

iwf-web/phpstan-rules
=====================

Custom rules for PHPStan for applications developed by IWF

1.2.0(2mo ago)0236[1 PRs](https://github.com/iwf-web/phpstan-rules/pulls)MITPHPPHP &gt;=8.3CI passing

Since Apr 14Pushed 1mo agoCompare

[ Source](https://github.com/iwf-web/phpstan-rules)[ Packagist](https://packagist.org/packages/iwf-web/phpstan-rules)[ Docs](https://github.com/iwf-web/phpstan-rules)[ RSS](/packages/iwf-web-phpstan-rules/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (4)Dependencies (7)Versions (9)Used By (0)

IWF PHPStan Rules
=================

[](#iwf-phpstan-rules)

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

[![License](https://camo.githubusercontent.com/fc62b4a6c00e38ca712cd7eda313c697bb8b0c061868fe2c1a6e147c8bf45e5e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6977662d7765622f7068707374616e2d72756c6573)](https://github.com/iwf-web/phpstan-rules/blob/main/LICENSE.txt)[![Version](https://camo.githubusercontent.com/d23d2b05e45658e0347460559f4d8e1f1046433c906277f2d7107b864f31c619/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6977662d7765622f7068707374616e2d72756c65733f6c6162656c3d6c617465737425323072656c65617365)](https://packagist.org/packages/iwf-web/phpstan-rules)[![Version (including pre-releases)](https://camo.githubusercontent.com/cc750f6cc595f7bcd55b00f5d905f4bc3bfed62370b0b885aa8489c740a2f5aa/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6977662d7765622f7068707374616e2d72756c65733f696e636c7564655f70726572656c6561736573266c6162656c3d6c61746573742532307072652d72656c65617365)](https://packagist.org/packages/iwf-web/phpstan-rules)[![Downloads on Packagist](https://camo.githubusercontent.com/9c2e0ef46abd2c532d6a9e5bbefcca0ae3559e46c1d0d281195632496e234106/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6977662d7765622f7068707374616e2d72756c6573)](https://packagist.org/packages/iwf-web/phpstan-rules)[![Coverage](https://camo.githubusercontent.com/04e18a1c22c90a6a13eaee74733b36e2d17579a33edc0e2720065deabf5de797/68747470733a2f2f736f6e61722e6977662e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d7068707374616e2d72756c6573266d65747269633d636f76657261676526746f6b656e3d7371625f37313165396536326631336436613266666564633738653265346365353937653836613031303863)](https://sonar.iwf.io/dashboard?id=phpstan-rules)

Requirements
------------

[](#requirements)

- PHP 8.3 or higher
- PHPStan ^2.1

Installation
------------

[](#installation)

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

Usage
-----

[](#usage)

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

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

### Configuration

[](#configuration)

Several rules require or accept configuration parameters under the `iwfWeb` key.

#### Controller rules

[](#controller-rules)

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

#### Required use aliases

[](#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

[](#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'
                    excludedClasses:
                        - 'App\Controller\Api\Security\LoginController'
            excludedClasses:
                - 'App\Controller\Api\Security\LoginController'
```

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

[](#force-dateprovider-requires-coaladate-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`)

[](#handle-bus-traits-requires-coalamessenger-bundle)

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

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

[](#require-invalid-data-test-group-requires-coalatesting-bundle)

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

---

Rules
-----

[](#rules)

### Common

[](#common)

#### `iwfWeb.mbFunctionUsageRule` — Multibyte function usage

[](#iwfwebmbfunctionusagerule--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

[](#iwfwebnoannotationasattribute--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

[](#iwfwebrequiredusealias--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

[](#iwfwebattributerequirements--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

[](#controller)

#### `iwfWeb.controllerHandleReturnType` — Controller handle() return type

[](#iwfwebcontrollerhandlereturntype--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\]

[](#iwfwebcontrollermissingisgranted--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

[](#coala--dateprovider)

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

#### `iwfWeb.forceDateProviderNew` / `iwfWeb.forceDateProviderFuncCall` / `iwfWeb.forceDateProviderStaticCall`

[](#iwfwebforcedateprovidernew--iwfwebforcedateproviderfunccall--iwfwebforcedateproviderstaticcall)

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

[](#coala--messenger)

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

#### `iwfWeb.useHandleBusTrait`

[](#iwfwebusehandlebustrait)

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

[](#coala--testing)

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

#### `iwfWeb.requireInvalidDataTestGroup`

[](#iwfwebrequireinvaliddatatestgroup)

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
-----------

[](#development)

### Prerequisites

[](#prerequisites)

- Docker with Compose

### Bootstrap

[](#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

[](#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

[](#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

[](#running-composer-commands)

```
bin/composer.sh
```

Runs Composer inside the default Docker container. Examples:

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

### Debugging with Xdebug

[](#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
------------

[](#contributing)

Please read [CONTRIBUTING.md](https://github.com/iwf-web/.github/blob/main/CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.

This project uses [Conventional Commits](https://www.conventionalcommits.org/) for automated releases and changelog generation.

Versioning
----------

[](#versioning)

We use [SemVer](http://semver.org/) for versioning. For available versions, see the [tags on this repository](https://github.com/iwf-web/phpstan-rules/tags).

Authors
-------

[](#authors)

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

[](#special-thanks-for-all-the-people-who-had-helped-this-project-so-far)

- **Oliver** - [Oliver-Zieschang](https://github.com/Oliver-Zieschang)

See also the full list of [contributors](https://github.com/iwf-web/phpstan-rules/contributors) who participated in this project.

### I would like to join this list. How can I help the 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](https://github.com/iwf-web/.github/blob/main/CONTRIBUTING.md) guide.

License
-------

[](#license)

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

Acknowledgments
---------------

[](#acknowledgments)

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

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance89

Actively maintained with recent releases

Popularity16

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 66.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~6 days

Total

4

Last Release

80d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/fd2436742c25806c5fb55e04d5292ddf57f7ae28e79f10bb926648d15267ccfe?d=identicon)[iwf-web](/maintainers/iwf-web)

---

Top Contributors

[![Oliver-Zieschang](https://avatars.githubusercontent.com/u/266786970?v=4)](https://github.com/Oliver-Zieschang "Oliver-Zieschang (18 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (5 commits)")[![iwf-web-bot](https://avatars.githubusercontent.com/u/250552481?v=4)](https://github.com/iwf-web-bot "iwf-web-bot (4 commits)")

---

Tags

phpphpstanphpstan-rulesstandardsPHPStanrulesCoding Standardruleset

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/iwf-web-phpstan-rules/health.svg)

```
[![Health](https://phpackages.com/badges/iwf-web-phpstan-rules/health.svg)](https://phpackages.com/packages/iwf-web-phpstan-rules)
```

###  Alternatives

[ruler/ruler

A simple stateless production rules engine for modern PHP.

1.1k835.4k4](/packages/ruler-ruler)[hybridlogic/validation

A simple, extensible validation library for PHP with support for filtering and validating any input array along with generating client side validation code.

641.1k](/packages/hybridlogic-validation)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
