PHPackages                             efabrica/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. efabrica/phpstan-rules

ActiveLibrary[Testing &amp; Quality](/categories/testing)

efabrica/phpstan-rules
======================

0.8.1(5mo ago)23.3k4[2 issues](https://github.com/efabrica-team/phpstan-rules/issues)[2 PRs](https://github.com/efabrica-team/phpstan-rules/pulls)1MITPHPPHP &gt;=7.4 &lt;8.5CI passing

Since Aug 9Pushed 2mo ago4 watchersCompare

[ Source](https://github.com/efabrica-team/phpstan-rules)[ Packagist](https://packagist.org/packages/efabrica/phpstan-rules)[ RSS](/packages/efabrica-phpstan-rules/feed)WikiDiscussions main Synced today

READMEChangelog (5)Dependencies (8)Versions (23)Used By (1)

eFabrica PHPStan extension
==========================

[](#efabrica-phpstan-extension)

Extension for PHPStan is providing several services and rules to help find bugs in your applications.

[![PHP unit](https://github.com/efabrica-team/phpstan-rules/workflows/PHPunit/badge.svg)](https://github.com/efabrica-team/phpstan-rules/actions?query=workflow%3APHPunit)[![PHPStan level](https://camo.githubusercontent.com/8eff2a8ac302a6e989418c7e571870ff5d8fe9db395c6bc3381d1052856a7751/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c3a2532306d61782d627269676874677265656e2e737667)](https://github.com/efabrica-team/phpstan-rules/actions?query=workflow%3A%22PHP+static+analysis%22)[![PHP static analysis](https://github.com/efabrica-team/phpstan-rules/workflows/PHP%20static%20analysis/badge.svg)](https://github.com/efabrica-team/phpstan-rules/actions?query=workflow%3A%22PHP+static+analysis%22)[![Latest Stable Version](https://camo.githubusercontent.com/d8a34dbefee0daf128fdbe8c352ddd4c6e2cb143639eea92138a107d56e2bce2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f65666162726963612f7068707374616e2d72756c65732e737667)](https://packagist.org/packages/efabrica/phpstan-rules)[![Total Downloads](https://camo.githubusercontent.com/4e3b3ea56d7680665b76b1b31904c732247d72df752b68b85804e6a589b0c6fc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f65666162726963612f7068707374616e2d72756c65732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/efabrica/phpstan-rules)

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

[](#installation)

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

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

```

Setup
-----

[](#setup)

This extension adds several rules. You can use them all by including these files in your `phpstan.neon`:

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

Or include just:

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

and pick rules you want to use

### Guzzle - ClientCallWithoutOptionRule

[](#guzzle---clientcallwithoutoptionrule)

Finds all calls of GuzzleHttp\\Client methods without some option e.g. timeout, connect\_timeout

```
services:
    -
        factory: Efabrica\PHPStanRules\Rule\Guzzle\ClientCallWithoutOptionRule(['timeout', 'connect_timeout'])
        tags:
            - phpstan.rules.rule
```

```
use GuzzleHttp\Client;

$guzzleClient = new Client();
$guzzleClient->request('GET', 'https://example.com/api/url');
```

❌

```
use GuzzleHttp\Client;

$guzzleClient = new Client();
$guzzleClient->request('GET', 'https://example.com/api/url', ['timeout' => 3, 'connect_timeout' => 1]);
```

👍

### Tomaj/Nette API - InputParamNameRule

[](#tomajnette-api---inputparamnamerule)

Checks if names of all input parameters. Every name has to contain only alphanumeric characters and `_`

```
services:
    -
        factory: Efabrica\PHPStanRules\Rule\Tomaj\NetteApi\InputParamNameRule
        tags:
            - phpstan.rules.rule
```

```
use Tomaj\NetteApi\Handlers\BaseHandler;

final class SomeHandler extends BaseHandler
{
    public function params(): array
    {
        return [
            new GetInputParam('my-name')
        ];
    }
}
```

❌

```
use Tomaj\NetteApi\Handlers\BaseHandler;

final class SomeHandler extends BaseHandler
{
    public function params(): array
    {
        return [
            new GetInputParam('my_name')
        ];
    }
}
```

👍

### Check trait context - TraitContextRule

[](#check-trait-context---traitcontextrule)

Checks if traits are used only in context of classes specified in them via comment `@context {Type}`

```
services:
    -
        factory: Efabrica\PHPStanRules\Rule\General\TraitContextRule
        tags:
            - phpstan.rules.rule
```

```
/**
 * @context MyInterface
 */
trait MyTrait
{

}

final class SomeClass
{
    use MyTrait;
}
```

❌

```
/**
 * @context MyInterface
 */
trait MyTrait
{

}

final class SomeClass implements MyInterface
{
    use MyTrait;
}
```

👍

### Check calling method in object method

[](#check-calling-method-in-object-method)

Checks if some method is not used in disabled context - specific method of object.

```
parameters:
    disabledMethodCalls:
        -
            context: 'WithCallInterface::checkedMethod'
            disabled: 'ClassWithDisabledMethod::disabledMethod'

services:
    -
        factory: Efabrica\PHPStanRules\Rule\General\DisableMethodCallInContextRule(%disabledMethodCalls%)
        tags:
            - phpstan.rules.rule
```

```
class ClassWithDisabledMethod implements WithDisabledMethodInterface
{
    public function disabledMethod() {} // this method shouldn't be called in WithCallInterface::checkedMethod
}
```

```
final class SomeClass implements WithCallInterface
{
    public function checkedMethod(): array
    {
        return [(new ClassWithDisabledMethod)->disabledMethod()]
    }
}
```

❌

```
final class SomeClass implements WithCallInterface
{
    public function checkedMethod(): array
    {
        return [(new ClassWithDisabledMethod)]
    }
}
```

👍

### Check calling method with required parameters

[](#check-calling-method-with-required-parameters)

Checks if some method is called with all required parameters with corresponding types.

```
parameters:
    requiredParametersInMethodCalls:
        -
            context: 'SomeClass::someMethod'
            parameters:
                -
                    name: someParameter
                    type: string
                    tip: 'Always use parameter someParameter as string because...'

services:
    -
        factory: Efabrica\PHPStanRules\Rule\General\RequiredParametersInMethodCallRule(%requiredParametersInMethodCalls%)
        tags:
            - phpstan.rules.rule
```

```
class SomeClass
{
    public function someMethod(?string $someParameter = null): void
    {
        // this method should be called with string value of $someParameter
    }
}
```

```
class Foo
{
    public function bar(SomeClass $someClass)
    {
        $someClass->someMethod();
    }
}
```

❌

```
class Foo
{
    public function bar(SomeClass $someClass)
    {
        $someClass->someMethod('baz');
    }
}
```

👍

### Do not concatenate translated strings

[](#do-not-concatenate-translated-strings)

Every language has its own word order in sentences, we can't use e.g. variables at the same place for all languages. There are mechanisms in translate libraries e.g. symfony/translator - we can use placeholders like %name% etc. This rule checks if you use translated messages and then concat them with some other strings.

```
parameters:
    translateCalls:
        - iAmTranslateFunction
        - Efabrica\PHPStanRules\Tests\Rule\General\DisabledConcatenationWithTranslatedStringsRule\Source\TranslatorInterface::iAmTranslateMethod
        - Efabrica\PHPStanRules\Tests\Rule\General\DisabledConcatenationWithTranslatedStringsRule\Source\TranslatorInterface::iAmTranslateStaticMethod
    allowedTranslateConcatenationPatterns:
        - '[\s]*[\s]*[\s]*'
        - '[\s]*This is allowed text[\s]*'
        - '[\s]*\#[0-9]+[\s]*'

services:
    -
        factory: Efabrica\PHPStanRules\Rule\General\DisabledConcatenationWithTranslatedStringsRule(%translateCalls%)
        tags:
            - phpstan.rules.rule
```

```
$message = 'Hello';
$name = 'Mark';
echo $translator->iAmTranslateMethod($message) . ' ' . $name;
```

❌

```
$message = 'Hello %name%';
$name = 'Mark';
echo $translator->iAmTranslateMethod($message, ['name' => $name];
```

👍

### Forbidden constructor parameters types

[](#forbidden-constructor-parameters-types)

This rule checks if constructor contains forbidden parameter types.

```
parameters:
    forbiddenConstructorParametersTypes:
        -
            context: 'SomeClass'
            forbiddenTypes:
                -
                    type: ForbiddenType
                    tip: 'ForbiddenType is not allowed, use NotForbiddenType instead'

services:
    -
        factory: Efabrica\PHPStanRules\Rule\General\ForbiddenConstructorParametersTypesRule(%forbiddenConstructorParametersTypes%)
        tags:
            - phpstan.rules.rule
```

```
class SomeClass
{

}

class ForbiddenType
{

}

class NotForbiddenType
{

}
```

```
class Foo extends SomeClass
{
    public function __construct(ForbiddenType $type)
    {

    }
}
```

❌

```
class Foo extends SomeClass
{
    public function __construct(NotForbiddenType $type)
    {

    }
}
```

👍

### Enforce arrow function

[](#enforce-arrow-function)

Checks closures and reports those that only contain a single return expression, because they can be replaced with `fn`. This rule is optional and is not enabled by default in `rules.neon`.

```
services:
    -
        factory: Efabrica\PHPStanRules\Rule\General\EnforceArrowFunctionRule
        tags:
            - phpstan.rules.rule
```

```
$doubled = array_map(function (int $number): int {
    return $number * 2;
}, $numbers);
```

❌

```
$doubled = array_map(fn (int $number): int => $number * 2, $numbers);
```

👍

### Performance - DisabledCallsInLoopsRule

[](#performance---disabledcallsinloopsrule)

Some functions are not recommended to be called in loops. For example array\_merge.

```
services:
    -
        factory: Efabrica\PHPStanRules\Rule\Performance\DisabledCallsInLoopsRule
        tags:
            - phpstan.rules.rule
```

```
$result = [];
for ($i = 0; $i < 100; $i++) {
    $result = array_merge($result, $data[$i]);
}
```

❌

```
$result = array_merge([], ...$data);
```

👍

### Performance - UseNetteDatabaseSelectionFetchTogetherWithLimitRule

[](#performance---usenettedatabaseselectionfetchtogetherwithlimitrule)

Nette\\Database\\Table\\Selection::fetch() should be used with limit(1) to avoid loading more rows than needed.

```
services:
    -
        factory: Efabrica\PHPStanRules\Rule\Performance\UseNetteDatabaseSelectionFetchTogetherWithLimitRule
        tags:
            - phpstan.rules.rule
```

```
return $selection->where(['category_id' => 1])->fetch();
```

❌

```
return $selection->where(['category_id' => 1])->limit(1)->fetch();
```

👍

### Check calls in conditions

[](#check-calls-in-conditions)

This rule checks if there are some (slow) calls (function call, method call, static method call) in if conditions before other expressions. There can be set list of slow calls in parameters. If not set, all calls are considered slower than other expressions.

```
parameters:
    conditionSlowCalls:
        - 'file_*'            # all functions starting with file_
        - 'Foo\Bar\Baz->foo'  # method foo called on object of type Foo\Bar\Baz
        - 'Foo\Bar\Baz::bar'  # static method bar from Foo\Bar\Baz
```

```
class SomeClass
{
    public function doSomething(bool $someOption): void
    {
        if (file_exists($someFile) && $someOption) {
            // do something
        }
    }
}
```

❌

```
class SomeClass
{
    public function doSomething(bool $someOption): void
    {
        if ($someOption && file_exists($someFile)) {
            // do something
        }
    }
}
```

👍

### Performance - UseArrayComparisonInsteadOfCountInConditionRule

[](#performance---usearraycomparisoninsteadofcountinconditionrule)

This rule checks if `count($array)` is used in `if` / `elseif` conditions for empty/non-empty checks and recommends array comparison with `[]`.

```
services:
    -
        factory: Efabrica\PHPStanRules\Rule\Performance\UseArrayComparisonInsteadOfCountInConditionRule
        tags:
            - phpstan.rules.rule
```

```
if (count($items) > 0) {
    // ...
}
```

❌

```
if ($items !== []) {
    // ...
}
```

👍

### Nette DI - PresenterInjectedPropertiesExtension

[](#nette-di---presenterinjectedpropertiesextension)

Will not report uninitialized properties with `@Inject` or `#[Inject]` attribute.

```
services:
    -
        class: Efabrica\PHPStanRules\Rule\Nette\PresenterInjectedPropertiesExtension
        tags:
            - phpstan.properties.readWriteExtension
```

```
class InjectPresenter
{
    /** @var SomeInjectedClass @inject */
    public SomeInjectedClass $someService;
    ...

    #[Inject]
    public OtherInjectedClass $otherService;
    ...
```

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance58

Moderate activity, may be stable

Popularity24

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 90% 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 ~79 days

Total

17

Last Release

157d ago

PHP version history (6 changes)0.1.0PHP &gt;=7.4 &lt;8.2

0.2.0PHP &gt;=7.4 &lt;=8.2

0.4.2PHP &gt;=7.4 &lt;8.3

0.7.0PHP &gt;=7.4 &lt;=8.3

0.7.1PHP &gt;=7.4 &lt;8.4

0.7.6PHP &gt;=7.4 &lt;8.5

### Community

Maintainers

![](https://www.gravatar.com/avatar/25289c62a88df1c404543693ba52e44748dbce486bcfab91fc8c5931a6bb38e1?d=identicon)[dev-efabrica](/maintainers/dev-efabrica)

---

Top Contributors

[![lulco](https://avatars.githubusercontent.com/u/9377319?v=4)](https://github.com/lulco "lulco (63 commits)")[![michal-efabrica](https://avatars.githubusercontent.com/u/195872206?v=4)](https://github.com/michal-efabrica "michal-efabrica (3 commits)")[![jzernovic](https://avatars.githubusercontent.com/u/7045023?v=4)](https://github.com/jzernovic "jzernovic (2 commits)")[![riki137](https://avatars.githubusercontent.com/u/1223388?v=4)](https://github.com/riki137 "riki137 (1 commits)")[![romanmatyus](https://avatars.githubusercontent.com/u/1110294?v=4)](https://github.com/romanmatyus "romanmatyus (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[larastan/larastan

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

6.5k55.4M8.4k](/packages/larastan-larastan)[phpstan/phpstan-symfony

Symfony Framework extensions and rules for PHPStan

79475.7M2.2k](/packages/phpstan-phpstan-symfony)[phpstan/phpstan-doctrine

Doctrine extensions for PHPStan

67272.8M1.4k](/packages/phpstan-phpstan-doctrine)[shipmonk/dead-code-detector

Dead code detector to find unused PHP code via PHPStan extension. Can automatically remove dead PHP code. Supports libraries like Symfony, Doctrine, PHPUnit etc. Detects dead cycles. Can detect dead code that is tested.

4853.5M91](/packages/shipmonk-dead-code-detector)[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.

33422.6M549](/packages/spaze-phpstan-disallowed-calls)[tomasvotruba/cognitive-complexity

PHPStan rules to measure cognitive complexity of your classes and methods

1635.6M289](/packages/tomasvotruba-cognitive-complexity)

PHPackages © 2026

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