PHPackages                             nijidigital/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. [Testing &amp; Quality](/categories/testing)
4. /
5. nijidigital/phpstan-rules

ActivePhpstan-extension[Testing &amp; Quality](/categories/testing)

nijidigital/phpstan-rules
=========================

custom phpstan rules created by dsf-niji

v2.1.1(7mo ago)0731↓50%1[1 issues](https://github.com/NijiDigital/phpstan-rules/issues)MITPHPPHP &gt;=8.2

Since Sep 5Pushed 7mo ago1 watchersCompare

[ Source](https://github.com/NijiDigital/phpstan-rules)[ Packagist](https://packagist.org/packages/nijidigital/phpstan-rules)[ Docs](https://github.com/NijiDigital/phpstan-rules)[ RSS](/packages/nijidigital-phpstan-rules/feed)WikiDiscussions v1.x Synced 1mo ago

READMEChangelog (6)Dependencies (7)Versions (8)Used By (0)

nijidigital/phpstan-rules
=========================

[](#nijidigitalphpstan-rules)

Custom PhpStan rules made with ❤️ by [Niji](https://www.niji.fr).

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

[](#installation)

To use this extension, require it in [Composer](https://getcomposer.org/):

```
composer require --dev nijidigital/phpstan-rules
```

If you also install [phpstan/extension-installer](https://github.com/phpstan/extension-installer) then you're all set!

 Manual installationIf you don't want to use `phpstan/extension-installer`, include extension.neon in your project's PHPStan config:

```
includes:
    - vendor/nijidigital/phpstan-rules/extension.neon

```

Existing rules
--------------

[](#existing-rules)

### `NoRelativeDatetime`

[](#norelativedatetime)

Prevents usage of relative date/time strings and empty constructors in `DateTime` and `DateTimeImmutable` to ensure consistent and testable date handling.

#### Examples

[](#examples)

❌ **Invalid:**

```
// Empty constructors
$now = new \DateTime();
$now = new \DateTimeImmutable();

// Relative date strings
$yesterday = new \DateTime('yesterday');
$nextMonth = new \DateTime('next month');
$twoHoursLater = new \DateTimeImmutable('+2 hours');
```

✅ **Valid alternatives:**

```
// Use absolute dates for fixed dates
$fixedDate = new \DateTime('2025-07-01 13:12:11');

// Use ClockInterface for current time and modifications
function doSomethingWithTime(ClockInterface $clock) {
    $now = $clock->now();
    $yesterday = $clock->now()->modify('-1 day');
    $nextMonth = $clock->now()->modify('+1 month');

    // (...)
}
```

### `DoctrineMigrationsSafeMigration`

[](#doctrinemigrationssafemigration)

Detects potentially unsafe database migration operations that could break backward compatibility in Doctrine migrations. Operations can be marked as safe using PHPStan's standard `@phpstan-ignore` comment.

#### Examples

[](#examples-1)

❌ **Invalid:**

```
class UnsafeMigration extends AbstractMigration
{
    public function up(Schema $schema): void
    {
        // These operations may not be backward compatible
        $this->addSql('DROP TABLE user');
        $this->addSql('ALTER TABLE user CHANGE name email VARCHAR(255)');
        $this->addSql('ALTER TABLE user DROP COLUMN name');
        $this->addSql('DROP DATABASE test');
        $this->addSql('TRUNCATE TABLE user');
    }
}
```

✅ **Valid alternatives:**

```
class SafeMigration extends AbstractMigration
{
    public function up(Schema $schema): void
    {
        // Safe operations (no ignore comment needed)
        $this->addSql('ALTER TABLE user ADD COLUMN email VARCHAR(255)');
        $this->addSql('CREATE INDEX idx_user_email ON user (email)');
        $this->addSql('INSERT INTO user (name) VALUES (\'John\')');

        // Unsafe operations marked as intentionally safe
        /* @phpstan-ignore doctrineMigrations.unsafeMigration */
        $this->addSql('DROP TABLE legacy_user');

        /* @phpstan-ignore doctrineMigrations.unsafeMigration */
        $this->addSql('ALTER TABLE user CHANGE name full_name VARCHAR(255)');
    }
}
```

#### Configuration

[](#configuration)

You can customize the behavior of this rule using the `parameters` section in your `phpstan.neon` configuration:

```
parameters:
    niji:
        doctrineMigrations:
            safeMigration:
                # Custom list of blacklisted SQL patterns with their error messages
                blacklistedQueries:
                    '/DROP\s+TABLE\s+/im': 'Dropping tables is not allowed'
                    '/ALTER\s+TABLE\s+.+\s+DROP\s+COLUMN/im': 'Dropping columns breaks backward compatibility'
```

**Available options:**

- `blacklistedQueries`: Array of regex patterns (as keys) with their corresponding error messages (as values). If not specified, uses default patterns for common unsafe operations.

### `DoctrineMigrationsDescription`

[](#doctrinemigrationsdescription)

Ensures that Doctrine migration classes provide meaningful descriptions by validating the return value of the `getDescription()` method against a configurable pattern.

#### Examples

[](#examples-2)

❌ **Invalid:**

```
class MyMigration extends AbstractMigration
{
    public function getDescription(): string
    {
        return ''; // Empty description
    }

    public function up(Schema $schema): void
    {
        $this->addSql('ALTER TABLE user ADD COLUMN email VARCHAR(255)');
    }
}
```

✅ **Valid:**

```
class MyMigration extends AbstractMigration
{
    public function getDescription(): string
    {
        return 'Add email column to user table';
    }

    public function up(Schema $schema): void
    {
        $this->addSql('ALTER TABLE user ADD COLUMN email VARCHAR(255)');
    }
}
```

#### Configuration

[](#configuration-1)

By default, the rule accepts any non-empty string. You can customize the accepted pattern using the `parameters` section in your `phpstan.neon` configuration:

```
parameters:
    niji:
        doctrineMigrations:
            description:
                # Custom regex pattern for migration descriptions
                acceptedPattern: '/^[A-Z][a-z0-9\s]+\.?$/'
```

**Available options:**

- `acceptedPattern`: A regex pattern that migration descriptions must match. Defaults to `/.+/im` (any non-empty string).

Troubleshooting
---------------

[](#troubleshooting)

### PhpStorm doesn't provide any autocomplete on PhpStan classes

[](#phpstorm-doesnt-provide-any-autocomplete-on-phpstan-classes)

Details Taken from \[this blog\]([https://blog.bitexpert.de/blog/phpstorm\_phpstan\_wsl2\_issue](https://blog.bitexpert.de/blog/phpstorm_phpstan_wsl2_issue)) : ```
1. Copy the file `vendor/phpstan/phpstan/phpstan.phar` to a local folder of your choice, ie : `C:\php_include_path`.
2. In PhpStorm, go to File | Settings | PHP and add your newly created folder to the include path.

```

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance63

Regular maintenance activity

Popularity18

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor2

2 contributors hold 50%+ of commits

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 ~4 days

Total

8

Last Release

226d ago

Major Versions

v1.0.0 → v2.0.02025-09-08

v1.1.0 → v2.1.02025-10-02

v1.x-dev → v2.1.12025-10-02

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/58166712?v=4)[Morgan NEUTE](/maintainers/niji-mneute)[@niji-mneute](https://github.com/niji-mneute)

![](https://avatars.githubusercontent.com/u/33158021?v=4)[alexandre HUBERT](/maintainers/niji-ahubert)[@niji-ahubert](https://github.com/niji-ahubert)

---

Top Contributors

[![niji-ahubert](https://avatars.githubusercontent.com/u/33158021?v=4)](https://github.com/niji-ahubert "niji-ahubert (5 commits)")[![niji-vlebiannic](https://avatars.githubusercontent.com/u/47846817?v=4)](https://github.com/niji-vlebiannic "niji-vlebiannic (4 commits)")[![niji-mneute](https://avatars.githubusercontent.com/u/58166712?v=4)](https://github.com/niji-mneute "niji-mneute (3 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisRector

Code StylePHP CS Fixer

### Embed Badge

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

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

###  Alternatives

[larastan/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

6.4k43.5M5.2k](/packages/larastan-larastan)[phpstan/phpstan-symfony

Symfony Framework extensions and rules for PHPStan

78268.9M1.5k](/packages/phpstan-phpstan-symfony)[phpstan/phpstan-doctrine

Doctrine extensions for PHPStan

66466.6M1.1k](/packages/phpstan-phpstan-doctrine)[phpat/phpat

PHP Architecture Tester

1.2k3.5M32](/packages/phpat-phpat)[spaze/phpstan-disallowed-calls

PHPStan rules to detect disallowed method &amp; function calls, constant, namespace, attribute, property &amp; superglobal usages, with powerful rules to re-allow a call or a usage in places where it should be allowed.

33120.0M375](/packages/spaze-phpstan-disallowed-calls)[mglaman/phpstan-drupal

Drupal extension and rules for PHPStan

20729.0M124](/packages/mglaman-phpstan-drupal)

PHPackages © 2026

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