efabrica / phpstan-rules
Installs: 2 122
Dependents: 1
Suggesters: 0
Security: 0
Stars: 2
Watchers: 4
Forks: 1
Open Issues: 7
Requires
- php: >=7.4 <8.4
- phpstan/phpstan: ^1.8
Requires (Dev)
- guzzlehttp/guzzle: ^7.3
- nikic/php-parser: ^4.14
- phpunit/phpunit: ^9.5
- tomaj/nette-api: ^2.7
- tracy/tracy: *
This package is auto-updated.
Last update: 2024-10-27 12:58:55 UTC
README
Extension for PHPStan is providing several services and rules to help find bugs in your applications.
Installation
To use this extension, require it in Composer:
composer require --dev efabrica/phpstan-rules
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
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
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
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
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
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
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
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) { } }
👍
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);
👍