PHP coding standard built on top of PHP_CodeSniffer and Slevomat Coding Standard rules.
- Install with
composer require --dev orisai/coding-standard
- Create
phpcs.xml
in root of your project- Or wherever you want, just modify paths (starting with ./) in xml file then.
- Insert following content
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="./vendor/squizlabs/php_codesniffer/phpcs.xsd"> <!-- Show only relevant part of path --> <arg name="basepath" value="./"/> <!-- Configure cache --> <arg name="cache" value="./var/tools/PHP_CodeSniffer/cache.dat"/> <!-- Import coding-standard --> <rule ref="./vendor/orisai/coding-standard/src/ruleset-<VERSION>.xml"/> <!-- Configure PSR-4 rule --> <rule ref="SlevomatCodingStandard.Files.TypeNameMatchesFileName"> <properties> <property name="rootNamespaces" type="array"> <element key="src" value="<NAMESPACE>"/> <element key="tests" value="Tests\<NAMESPACE>"/> </property> </properties> </rule> </ruleset>
- Replace
<VERSION>
with minimal php version you want to support- supported are
7.2
,7.3
,7.4
,8.0
,8.1
,8.2
,8.3
,8.4
- supported are
- Replace
<NAMESPACE>
with your root namespace- by default expected code directory is
src
and tests directory istests
withTests
namespace prefix
- by default expected code directory is
- Create directory for temp files
phpcs.xml
from example expects directoryvar/tools/PHP_CodeSniffer
(see<arg name="cache"
)
Check code
vendor/bin/phpcs --standard=phpcs.xml src tests
Fix errors
vendor/bin/phpcbf --standard=phpcs.xml src tests
You can always suppress rules instead of fixing the errors. Rules can be suppressed either locally, in path or entirely for project.
vendor/bin/phpcs
outputs all errors like this:
FILE: src/Example.php
---------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
---------------------------------
1 | ERROR | An error message.
| | (Name.Of.The.Sniff)
---------------------------------
The Name.Of.The.Sniff
printed in brackets under the error is the string which can be used to suppress the sniff, as
described below.
You can suppress rules by specific comments inside file, either for the whole file or part of it.
Suppress all rules in whole file
<?php
// phpcs:ignoreFile
Suppress rules in code between phpcs:disable
and phpcs:enable
// phpcs:disable
echo 'some php code';
// phpcs:enable
// phpcs:disable Name.Of.The.Sniff
echo 'some php code';
// phpcs:enable Name.Of.The.Sniff
Suppress rules on current and next line
// phpcs:ignore
echo 'some php code';
// phpcs:ignore Name.Of.The.Sniff
echo 'some php code';
Learn more in PHP_CodeSniffer docs
Suppress specific rule in a path
<ruleset>
<rule ref="Name.Of.The.Sniff">
<exclude-pattern>src/Example\.php</exclude-pattern>
</rule>
</ruleset>
You can also suppress all rules in a path
<ruleset>
<exclude-pattern>path/to/directory</exclude-pattern>
</ruleset>
The <exclude-pattern>
is treated like a regular expression
- ensure that
.
(.php
) is escaped (\.php
) *
is converted to.*
- learn more in PHP_CodeSniffer docs
<ruleset>
<exclude-pattern>src/*Test\.php</exclude-pattern>
</ruleset>
Inside of the coding standard importing rule you can suppress the rules it imports entirely
<ruleset>
<rule ref="Namespace.Sniff">
<exclude name="Namespace.Sniff"/>
<!-- OR -->
<exclude name="Namespace.Sniff.SpecificError"/>
</rule>
</ruleset>
These sniffs may break code due to incorrect phpdoc types or parent class/interface lacking native types.
If you are not ready to use them, just disable them entirely:
<ruleset>
<!-- Excluded because they are unsafe to auto-fix without tests or passing static analysis (e.g. PHPStan) -->
<!-- Adds declare(strict_types=1) -->
<!-- Unsafe when code is not strict types compatible -->
<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing">
<exclude name="SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing"/>
</rule>
<!-- Adds property type based on annotation typehint -->
<!-- Unsafe for overridden properties and properties with incorrect phpdoc type -->
<rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingNativeTypeHint">
<exclude name="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingNativeTypeHint"/>
</rule>
<!-- Adds function parameter type based on annotation typehint -->
<!-- Unsafe for overridden third-party methods and methods with incorrect parameter phpdoc type -->
<rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint">
<exclude name="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint"/>
</rule>
<!-- Adds function return type based on annotation typehint -->
<!-- Unsafe for overridden third-party methods and methods with incorrect return phpdoc type -->
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint">
<exclude name="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint"/>
</rule>
<!-- Replaces inline phpdoc with assert() when possible -->
<!-- Unsafe with incorrect phpdoc types -->
<rule ref="SlevomatCodingStandard.PHP.RequireExplicitAssertion">
<exclude name="SlevomatCodingStandard.PHP.RequireExplicitAssertion"/>
</rule>
<!-- Makes anonymous closures static when $this is not used inside them -->
<!-- May be unsafe if closure binding is used -->
<rule ref="SlevomatCodingStandard.Functions.StaticClosure">
<exclude name="SlevomatCodingStandard.Functions.StaticClosure"/>
</rule>
<!-- Causes changes in what PHPStan reports because PHPStan treats short and generic array syntax differently -->
<!-- User[]|ICollection (iterable ICollection of User) -> array<User>|ICollection (union) -->
<rule ref="SlevomatCodingStandard.TypeHints.DisallowArrayTypeHintSyntax">
<exclude name="SlevomatCodingStandard.TypeHints.DisallowArrayTypeHintSyntax"/>
</rule>
</ruleset>
Compatibility with specific untyped parent/interface properties, method parameters and method return types may be solved by local ignores:
class Example extends ClassNotDeclaringTheTypes
{
/**
* @var int
* @phpcsSuppress SlevomatCodingStandard.TypeHints.PropertyTypeHint
*/
protected $exampleProperty;
/**
* @param int $example
* @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
* @return int
* @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint
*/
protected function exampleMethod($example)
{
return $example;
}
}
Closures using binding to an instance cannot be static and must be ignored by static closure sniff:
// phpcs:disable SlevomatCodingStandard.Functions.StaticClosure
(fn () => $object->$name = $value)
->bindTo($object, get_class($object))();
// phpcs:enable
In case you use EditorConfig, here is an easy preset, compatible with our coding standard
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
indent_size = 4
[**.{yaml, yml}]
indent_style = space
indent_size=2
For PhpStorm IDE is available config compatible with our coding standard.
To use our code style options, navigate to File | Settings | Editor | Code Style | PHP, choose Import scheme option in dropdown menu and select config file from ide-config/.idea/php-config.xml in package directory.
We offer code generation templates compatible with our coding standard. To use them, follow instructions:
- Navigate to IDE configuration folder.
- Or navigate to project
.idea
folder to set templates for project only.
- Or navigate to project
- Copy into the folder the package
ide-config/.idea/fileTemplates
directory and override existing files.
Alternatively you can also import templates one by one via settings at File | Settings | Editor | File and Code Templates.