Try Live
Add Docs
Rankings
Pricing
Docs
Install
Install
Docs
Pricing
More...
More...
Try Live
Rankings
Enterprise
Create API Key
Add Docs
Slevomat Coding Standard
https://github.com/slevomat/coding-standard
Admin
Slevomat Coding Standard is a PHP_CodeSniffer standard that provides hundreds of sniffs for
...
Tokens:
17,693
Snippets:
256
Trust Score:
9
Update:
1 day ago
Context
Skills
Chat
Benchmark
79.7
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Slevomat Coding Standard Slevomat Coding Standard is a comprehensive PHP_CodeSniffer standard that provides over 100 sniffs organized into three main categories: functional sniffs that improve code safety and behavior, cleaning sniffs that detect dead code, and formatting sniffs for consistent code appearance. Built for PHP 7.4+ and PHP 8.0+, it integrates seamlessly with PHP_CodeSniffer to enforce best practices across PHP projects. The standard supports automatic fixing of most violations via `phpcbf`, local suppression of specific checks using `@phpcsSuppress` annotations, and extensive configuration options through XML rulesets. It's designed to complement existing coding standards by providing additional checks for modern PHP features including type hints, null coalescing operators, arrow functions, and PHP 8 attributes. ## Installation Install via Composer and configure with a custom ruleset. ```bash composer require --dev slevomat/coding-standard ``` ```xml <?xml version="1.0"?> <ruleset name="MyProject"> <config name="installed_paths" value="../../slevomat/coding-standard"/> <!-- Include specific sniffs --> <rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes"/> <rule ref="SlevomatCodingStandard.Arrays.TrailingArrayComma"/> <rule ref="SlevomatCodingStandard.Namespaces.UnusedUses"/> </ruleset> ``` ```bash # Run code sniffer vendor/bin/phpcs --standard=ruleset.xml --extensions=php -sp src tests # Auto-fix violations vendor/bin/phpcbf --standard=ruleset.xml --extensions=php -sp src tests ``` ## Type Hints ### DeclareStrictTypes Enforces `declare(strict_types = 1)` at the top of each PHP file with configurable spacing. ```xml <rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes"> <properties> <property name="declareOnFirstLine" value="false"/> <property name="linesCountBeforeDeclare" value="1"/> <property name="linesCountAfterDeclare" value="1"/> <property name="spacesCountAroundEqualsSign" value="1"/> </properties> </rule> ``` ```php <?php declare(strict_types = 1); namespace App; class UserService { // Class implementation } ``` ### ParameterTypeHint Checks for missing parameter type hints and reports useless `@param` annotations. ```xml <rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint"> <properties> <property name="enableObjectTypeHint" value="true"/> <property name="enableMixedTypeHint" value="true"/> <property name="enableUnionTypeHint" value="true"/> <property name="traversableTypeHints" type="array"> <element value="\Doctrine\Common\Collections\Collection"/> </property> </properties> </rule> ``` ```php // Before (violation) /** * @param int $id * @param string $name */ public function findUser($id, $name) {} // After (correct) public function findUser(int $id, string $name): ?User {} // Suppress when overriding parent method without type hints /** * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint * @param int $max */ public function createProgressBar($max = 0): ProgressBar {} ``` ### ReturnTypeHint Enforces native return type hints and detects useless `@return` annotations. ```xml <rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint"> <properties> <property name="enableStaticTypeHint" value="true"/> <property name="enableMixedTypeHint" value="true"/> <property name="enableUnionTypeHint" value="true"/> <property name="enableNeverTypeHint" value="true"/> </properties> </rule> ``` ```php // Before (violation) /** * @return User|null */ public function findById(int $id) {} // After (correct) public function findById(int $id): ?User {} // Union types (PHP 8.0+) public function process(int $id): User|array {} // Never return type (PHP 8.1+) public function fail(): never { throw new RuntimeException('Failed'); } ``` ### PropertyTypeHint Requires native property type hints and detects useless `@var` annotations. ```xml <rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint"> <properties> <property name="enableNativeTypeHint" value="true"/> <property name="enableMixedTypeHint" value="true"/> <property name="enableUnionTypeHint" value="true"/> </properties> </rule> ``` ```php // Before (violation) class User { /** @var string */ private $name; /** @var int|null */ private $age; } // After (correct) class User { private string $name; private ?int $age; } ``` ### UnionTypeHintFormat Enforces consistent formatting of union type hints. ```xml <rule ref="SlevomatCodingStandard.TypeHints.UnionTypeHintFormat"> <properties> <property name="withSpaces" value="no"/> <property name="shortNullable" value="yes"/> <property name="nullPosition" value="last"/> </properties> </rule> ``` ```php // Correct (with settings above) public function process(string|int $value): User|null {} // Using short nullable syntax public function find(int $id): ?User {} ``` ## Namespaces ### AlphabeticallySortedUses Enforces alphabetically sorted `use` declarations with natural sorting. ```xml <rule ref="SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses"> <properties> <property name="psr12Compatible" value="true"/> <property name="caseSensitive" value="false"/> </properties> </rule> ``` ```php <?php namespace App\Services; use App\Entity\User; use App\Repository\UserRepository; use Doctrine\ORM\EntityManagerInterface; use Psr\Log\LoggerInterface; class UserService { // Implementation } ``` ### UnusedUses Detects and removes unused `use` imports. ```xml <rule ref="SlevomatCodingStandard.Namespaces.UnusedUses"> <properties> <property name="searchAnnotations" value="true"/> <property name="ignoredAnnotationNames" type="array"> <element value="@testCase"/> </property> </properties> </rule> ``` ```php // Before (violation - DateTime is unused) use App\Entity\User; use DateTime; class UserService { public function create(User $user): void {} } // After (correct) use App\Entity\User; class UserService { public function create(User $user): void {} } ``` ### ReferenceUsedNamesOnly Requires using `use` statements instead of fully qualified names. ```xml <rule ref="SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly"> <properties> <property name="searchAnnotations" value="true"/> <property name="allowFullyQualifiedGlobalClasses" value="false"/> <property name="allowFullyQualifiedGlobalFunctions" value="false"/> <property name="allowFullyQualifiedGlobalConstants" value="false"/> <property name="allowFallbackGlobalFunctions" value="false"/> <property name="allowFallbackGlobalConstants" value="false"/> </properties> </rule> ``` ```php // Before (violation) class UserService { public function now(): \DateTimeImmutable { return new \DateTimeImmutable(); } } // After (correct) use DateTimeImmutable; class UserService { public function now(): DateTimeImmutable { return new DateTimeImmutable(); } } ``` ### FullyQualifiedExceptions Requires exceptions to be referenced with fully qualified names for clarity. ```xml <rule ref="SlevomatCodingStandard.Namespaces.FullyQualifiedExceptions"> <properties> <property name="specialExceptionNames" type="array"> <element value="Throwable"/> </property> </properties> </rule> ``` ```php // Correct - fully qualified exception names try { $this->process(); } catch (\App\Exception\ValidationException $e) { // Handle validation error } catch (\RuntimeException $e) { // Handle runtime error } catch (\Exception $e) { // Handle general exception } ``` ## Classes ### ClassStructure Enforces consistent ordering of class members (constants, properties, methods). ```xml <rule ref="SlevomatCodingStandard.Classes.ClassStructure"> <properties> <property name="groups" type="array"> <element value="uses"/> <element value="public constants"/> <element value="protected constants"/> <element value="private constants"/> <element value="public static properties"/> <element value="protected static properties"/> <element value="private static properties"/> <element value="public properties"/> <element value="protected properties"/> <element value="private properties"/> <element value="constructor"/> <element value="static constructors"/> <element value="destructor"/> <element value="public static methods"/> <element value="public methods"/> <element value="protected static methods"/> <element value="protected methods"/> <element value="private static methods"/> <element value="private methods"/> <element value="magic methods"/> </property> </properties> </rule> ``` ```php class User { use TimestampableTrait; public const STATUS_ACTIVE = 'active'; private const STATUS_INACTIVE = 'inactive'; private static int $instanceCount = 0; private string $name; private ?string $email = null; public function __construct(string $name) { $this->name = $name; self::$instanceCount++; } public static function create(string $name): self { return new self($name); } public function getName(): string { return $this->name; } private function validate(): bool { return strlen($this->name) > 0; } } ``` ### ClassConstantVisibility Requires visibility declaration for class constants. ```xml <rule ref="SlevomatCodingStandard.Classes.ClassConstantVisibility"> <properties> <property name="fixable" value="true"/> </properties> </rule> ``` ```php // Before (violation) class Status { const ACTIVE = 'active'; const INACTIVE = 'inactive'; } // After (correct) class Status { public const ACTIVE = 'active'; private const INACTIVE = 'inactive'; } ``` ### RequireConstructorPropertyPromotion Requires PHP 8.0+ constructor property promotion. ```xml <rule ref="SlevomatCodingStandard.Classes.RequireConstructorPropertyPromotion"> <properties> <property name="enable" value="true"/> </properties> </rule> ``` ```php // Before (violation in PHP 8.0+) class User { private string $name; private int $age; public function __construct(string $name, int $age) { $this->name = $name; $this->age = $age; } } // After (correct) class User { public function __construct( private string $name, private int $age, ) {} } ``` ### ModernClassNameReference Enforces using `::class` constant instead of magic methods. ```xml <rule ref="SlevomatCodingStandard.Classes.ModernClassNameReference"> <properties> <property name="enableOnObjects" value="true"/> </properties> </rule> ``` ```php // Before (violation) $className = get_class($object); $parentClass = get_parent_class($this); $class = __CLASS__; // After (correct) $className = $object::class; $parentClass = parent::class; $class = self::class; ``` ## Control Structures ### EarlyExit Requires early exit to reduce nesting and improve readability. ```xml <rule ref="SlevomatCodingStandard.ControlStructures.EarlyExit"> <properties> <property name="ignoreStandaloneIfInScope" value="true"/> <property name="ignoreOneLineTrailingIf" value="true"/> </properties> </rule> ``` ```php // Before (violation) public function process(array $items): void { if (count($items) > 0) { foreach ($items as $item) { if ($item->isValid()) { $this->handle($item); } } } } // After (correct) public function process(array $items): void { if (count($items) === 0) { return; } foreach ($items as $item) { if (!$item->isValid()) { continue; } $this->handle($item); } } ``` ### RequireNullCoalesceOperator Requires null coalesce operator `??` when possible. ```php // Before (violation) $value = isset($data['key']) ? $data['key'] : 'default'; $name = $user !== null ? $user->getName() : 'Anonymous'; // After (correct) $value = $data['key'] ?? 'default'; $name = $user?->getName() ?? 'Anonymous'; ``` ### RequireNullCoalesceEqualOperator Requires null coalesce equal operator `??=` when possible (PHP 7.4+). ```xml <rule ref="SlevomatCodingStandard.ControlStructures.RequireNullCoalesceEqualOperator"> <properties> <property name="enable" value="true"/> </properties> </rule> ``` ```php // Before (violation) if ($this->cache === null) { $this->cache = []; } $data['key'] = $data['key'] ?? 'default'; // After (correct) $this->cache ??= []; $data['key'] ??= 'default'; ``` ### DisallowYodaComparison Disallows Yoda conditions for improved readability. ```php // Before (violation - Yoda style) if (null === $value) {} if ('active' === $status) {} // After (correct) if ($value === null) {} if ($status === 'active') {} ``` ## Functions ### RequireArrowFunction Requires arrow functions when possible (PHP 7.4+). ```xml <rule ref="SlevomatCodingStandard.Functions.RequireArrowFunction"> <properties> <property name="allowNested" value="true"/> <property name="enable" value="true"/> </properties> </rule> ``` ```php // Before (violation) $doubled = array_map(function ($n) { return $n * 2; }, $numbers); $filtered = array_filter($users, function ($user) use ($minAge) { return $user->getAge() >= $minAge; }); // After (correct) $doubled = array_map(fn($n) => $n * 2, $numbers); $filtered = array_filter($users, fn($user) => $user->getAge() >= $minAge); ``` ### StaticClosure Reports closures not using `$this` that should be declared static. ```php // Before (violation) $callback = function (int $value): int { return $value * 2; }; // After (correct) $callback = static function (int $value): int { return $value * 2; }; // Or using arrow function $callback = static fn(int $value): int => $value * 2; ``` ### RequireTrailingCommaInCall Requires trailing commas in multi-line function calls. ```xml <rule ref="SlevomatCodingStandard.Functions.RequireTrailingCommaInCall"> <properties> <property name="enable" value="true"/> </properties> </rule> ``` ```php // Correct $result = $this->service->process( $param1, $param2, $param3, ); $user = new User( name: 'John', email: 'john@example.com', age: 30, ); ``` ### UnusedParameter Detects unused function/method parameters. ```xml <rule ref="SlevomatCodingStandard.Functions.UnusedParameter"> <properties> <property name="allowedParameterPatterns" type="array"> <element value="/^_/"/> </property> </properties> </rule> ``` ```php // Violation - $logger is unused public function process(Request $request, LoggerInterface $logger): Response { return new Response($request->getContent()); } // Correct - prefix unused parameter with underscore public function process(Request $request, LoggerInterface $_logger): Response { return new Response($request->getContent()); } ``` ## Arrays ### TrailingArrayComma Enforces trailing commas in multi-line arrays for cleaner diffs. ```xml <rule ref="SlevomatCodingStandard.Arrays.TrailingArrayComma"> <properties> <property name="enableAfterHeredoc" value="true"/> </properties> </rule> ``` ```php // Correct $config = [ 'database' => [ 'host' => 'localhost', 'port' => 3306, 'name' => 'app', ], 'cache' => [ 'driver' => 'redis', 'prefix' => 'app_', ], ]; ``` ### AlphabeticallySortedByKeys Requires array keys to be sorted alphabetically. ```php // Before (violation) $config = [ 'name' => 'App', 'debug' => true, 'cache' => true, ]; // After (correct) $config = [ 'cache' => true, 'debug' => true, 'name' => 'App', ]; ``` ## Commenting ### DocCommentSpacing Enforces consistent spacing in doc comments. ```xml <rule ref="SlevomatCodingStandard.Commenting.DocCommentSpacing"> <properties> <property name="linesCountBeforeFirstContent" value="0"/> <property name="linesCountBetweenDescriptionAndAnnotations" value="1"/> <property name="linesCountBetweenDifferentAnnotationsTypes" value="0"/> <property name="linesCountAfterLastContent" value="0"/> <property name="annotationsGroups" type="array"> <element value="@ORM\"/> <element value="@param,@return,@throws"/> </property> </properties> </rule> ``` ```php /** * Creates a new user in the system. * * @ORM\PrePersist * * @param string $name User's full name * @param string $email User's email address * @return User The created user entity * @throws ValidationException If validation fails */ public function createUser(string $name, string $email): User { // Implementation } ``` ### ForbiddenAnnotations Reports forbidden annotations that should not be used. ```xml <rule ref="SlevomatCodingStandard.Commenting.ForbiddenAnnotations"> <properties> <property name="forbiddenAnnotations" type="array"> <element value="@author"/> <element value="@created"/> <element value="@version"/> <element value="@package"/> <element value="@copyright"/> <element value="@license"/> </property> </properties> </rule> ``` ### UselessFunctionDocComment Reports useless doc comments that don't add information beyond native types. ```php // Before (useless - will be reported) /** * @param int $id * @return User|null */ public function find(int $id): ?User {} // After (correct - no doc comment needed) public function find(int $id): ?User {} // Useful doc comment (provides additional info) /** * Finds a user by their unique identifier. * * @param int $id The user's database ID * @return User|null Returns null if user not found * @throws DatabaseException If database connection fails */ public function find(int $id): ?User {} ``` ## Exceptions ### DeadCatch Finds unreachable catch blocks. ```php // Violation - InvalidArgumentException catch is unreachable try { doStuff(); } catch (\Throwable $e) { log($e); } catch (\InvalidArgumentException $e) { // This is never reached! } // Correct - more specific exceptions first try { doStuff(); } catch (\InvalidArgumentException $e) { handleValidation($e); } catch (\Throwable $e) { log($e); } ``` ### ReferenceThrowableOnly Enforces catching `Throwable` instead of `Exception` for PHP 7.0+. ```php // Before (violation) try { $this->process(); } catch (Exception $e) { $this->log($e); } // After (correct) try { $this->process(); } catch (\Throwable $e) { $this->log($e); } ``` ### RequireNonCapturingCatch Requires non-capturing catch when exception variable is unused (PHP 8.0+). ```php // Before (violation - $e is unused) try { $this->process(); } catch (ValidationException $e) { return false; } // After (correct) try { $this->process(); } catch (ValidationException) { return false; } ``` ## Operators ### DisallowEqualOperators Disallows loose comparison operators for type safety. ```php // Before (violation) if ($value == null) {} if ($status != 'active') {} // After (correct) if ($value === null) {} if ($status !== 'active') {} ``` ### RequireCombinedAssignmentOperator Requires combined assignment operators. ```php // Before (violation) $count = $count + 1; $message = $message . ' suffix'; $total = $total * 2; // After (correct) $count += 1; $message .= ' suffix'; $total *= 2; ``` ## Variables ### UnusedVariable Detects unused variables in code. ```xml <rule ref="SlevomatCodingStandard.Variables.UnusedVariable"> <properties> <property name="ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach" value="true"/> </properties> </rule> ``` ```php // Violation $result = $this->calculate(); // $result is never used // Correct with foreach key-only usage foreach ($data as $key => $value) { echo $key; // $value intentionally unused } ``` ### UselessVariable Detects and removes useless intermediate variables. ```php // Before (violation) public function getName(): string { $name = $this->name; return $name; } // After (correct) public function getName(): string { return $this->name; } ``` ## Suppressing Sniffs Locally Suppress specific sniffs using `@phpcsSuppress` annotation. ```php class UserController { /** * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint * @param mixed $data */ public function process($data): void { // Process data that cannot have a native type hint } /** * @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter */ public function handle(Request $request, Response $response): void { // Required by interface but response is unused return $request->process(); } } ``` ## Summary Slevomat Coding Standard is designed for modern PHP development, particularly PHP 7.4+ and PHP 8.0+ projects. Key use cases include enforcing strict typing across entire codebases, maintaining consistent code structure within classes, detecting dead code and unused imports, and ensuring proper use of modern PHP features like constructor property promotion, arrow functions, and null coalescing operators. The standard integrates with CI/CD pipelines through PHP_CodeSniffer's CLI tools and supports incremental adoption by allowing selective sniff inclusion. Integration patterns typically involve creating a project-specific `ruleset.xml` that references desired sniffs with customized settings, running `phpcs` in pre-commit hooks or CI pipelines, and using `phpcbf` for automatic fixing. The standard works well alongside static analyzers like PHPStan and Psalm, providing complementary checks. For legacy projects, sniffs can be enabled incrementally, using exclusions and suppressions to manage the transition while maintaining consistent standards for new code.