-
-
Notifications
You must be signed in to change notification settings - Fork 73
Version 4.0 User Upgrade Guide
Caution
PHP_CodeSniffer 4.0.0 is currently in the pre-release phase. The information in this upgrade guide is subject to change until PHP_CodeSniffer 4.0.0 has been released.
If you find errors in this upgrade guide or would like to contribute improvements based on tests you've run with a PHP_CodeSniffer 4.0 pre-release, please open an issue.
PHP_CodeSniffer version 4.0.0 contains a number of core changes and breaks backwards compatibility in select situations. The aim of this guide is to help ruleset maintainers and end-users to upgrade from PHP_CodeSniffer version 3.x to version 4.x.
There is a separate Upgrade Guide for Sniff Developers and Integrators available.
It is highly recommended to upgrade as soon as you are able.
The PHP_CodeSniffer 3.x branch will no longer receive updates, with the exception of security fixes and runtime compatibility fixes for new PHP versions. This "limited support" will last a maximum of one year from the date of the PHP_Codesniffer 4.0.0 release.
If your project uses sniffs from external PHP_CodeSniffer standards, you will not be able to update until those external standards have been made compatible with PHP_CodeSniffer 4.0 and declared their compatibility.
This may take a little while. Please be patient and consider contributing to the project(s) if you get impatient (and even if you don't). 😉
- Start by updating your PHP_CodeSniffer install to the most recent 3.x release, 3.13.0 or higher.
- Action any and all deprecation notices which you see when running a scan with PHP_CodeSniffer on that version. That should get you most of the way there.
- Next, read through the step-by-step upgrade information below and take any additional actions which may be needed for your project.
Important
PHP_CodeSniffer 4.0 will more strictly enforce certain conventions sniffs need to comply with, so you may need to contact the author(s) of custom sniffs you use and/or maintainer(s) of external standards you use, to inform them of any issues you encounter.
Deprecation notices are just warnings about upcoming changes. Nothing has changed yet and everything will still work the same as before.
If you are not ready to upgrade to PHP_CodeSniffer 4.0, you can safely ignore the deprecation notices until you are.
If you want, you can even silence them by running PHP_CodeSniffer in quiet mode by using the -q
CLI flag.
This has no impact on the "code under scan", it just means that when running PHP_CodeSniffer, the minimum PHP version needs to be PHP 7.2. As an example, you can run PHP_CodeSniffer on PHP 8.4 to scan a code base which is supposed to run on PHP 5.6.
Previously it was not possible to overrule a <config>
directive set in an included ruleset from a top-level ("root") ruleset. Now you can.
For <config>
directives, the highest level ruleset will now take precedence. When the config
is set in two rulesets at the same inclusion level, the last included ruleset "wins".
Along the same lines, previously it was not possible to overrule a <arg>
directive set in an included ruleset from a top-level ("root") ruleset. Now you can.
For <arg>
directives, the highest level ruleset will now take precedence. When the arg
is set in two rulesets at the same inclusion level, the first included ruleset "wins".
To get round the old limitations, it was previously recommended to add a second included ruleset and include it either before or after the ruleset causing the "problem", depending on whether the overruling problem was related to a config
or an arg
directive.
In both cases, this will still work, but is no longer needed. The secondary ruleset can be removed and the directive being overruled can be moved to the project root ruleset.
The capability for PHP_CodeSniffer to scan JS/CSS files has been removed completely.
- PHP_CodeSniffer native sniffs will now only target PHP files.
- All PHP_CodeSniffer native CSS/JS specific sniffs have been removed. See Removed Sniffs.
Warning
This also means that the --extensions
command-line argument no longer takes a language "flavour" and that all files matching the (extension) criteria will now be scanned as if they were PHP files.
To continue running code style and code quality checks on JS and/or CSS files, use one of the many available dedicated JS/CSS scanning tools.
There are two kinds of sniffs which are affected by this:
- Sniffs which are specific to JS/CSS and only target JS/CSS code. If you use JS/CSS specific sniffs from either PHP_CodeSniffer itself or from an external standard, remove references to these sniffs from your ruleset.
- "Mixed" sniffs, i.e. sniffs which target both PHP as well as JS and/or CSS code. If an external standard you include in your ruleset contains these type of "mixed" sniffs, contact the maintainer of that standard about making the sniff compatible with PHP_CodeSniffer 4.0.
PHP_CodeSniffer >= 3.13.0 will show you deprecation notices for these sniffs to help you find them.
Secondly, review your extensions
settings.
- If you have
extensions
set in a ruleset, like<arg name="extensions" value="php,inc/php" />
, be sure to remove any non-PHP extensions. You can also remove the language part, i.e.php,inc/php
becomesphp,inc
. - Next, make sure to also check for any hard-coded commands which pass the
--extensions=...
CLI argument, like in continuous integration scripts. The same applies there: remove any non-PHP extensions and remove any potential language settings.
PHP_CodeSniffer 3.3.0 introduced a new syntax to set the value of array properties for sniffs by specifying array elements using a new element
tag with key
and value
attributes. The old syntax was deprecated in the same PHP_CodeSniffer version.
Support for the old syntax has been removed in PHP_CodeSniffer 4.0.0.
If you haven't done so already, search your [.]phpcs.xml[.dist]
file for type="array"
to find all array property settings and verify if these have been updated to use the new syntax.
Example of what the old syntax looked like:
<property name="forbiddenFunctions" type="array" value="sizeof=>count,delete=>unset,print=>echo,is_null=>null,create_function=>null"/>
The above property setting should be rewritten to the new syntax like so:
<property name="forbiddenFunctions" type="array">
<element key="sizeof" value="count"/>
<element key="delete" value="unset"/>
<element key="print" value="echo"/>
<element key="is_null" value="null"/>
<element key="create_function" value="null"/>
</property>
Note: the key
attribute on element
nodes is optional.
See the PHP_CodeSniffer 3.3.0 release notes for further information.
In PHP_CodeSniffer 4.0, all PHP_CodeSniffer native JS/CSS specific sniffs, as well as the sniffs from the MySource
standard, have been removed.
Referencing a removed sniff from a (custom) ruleset will result in a "Referenced sniff does not exist" error.
If you haven't done so already, search your [.]phpcs.xml[.dist]
file for...
Search for | Replace with |
---|---|
Generic.Debug.* |
(no replacement) |
Generic.Formatting.NoSpaceAfterCast |
Generic.Formatting.SpaceAfterCast and set the spacing property of that sniff to 0`. |
Generic.Functions.CallTimePassByReference |
(no replacement) Consider using the PHPCompatibility standard for detecting removed PHP features. |
MySource.* |
(no replacement) |
Squiz.Classes.DuplicateProperty |
(no replacement) |
Squiz.CSS.* |
(no replacement) |
Squiz.Debug.* |
(no replacement) |
Squiz.Objects.DisallowObjectStringIndex |
(no replacement) |
Squiz.Objects.ObjectMemberComma |
(no replacement) |
Squiz.WhiteSpace.LanguageConstructSpacing |
Generic.WhiteSpace.LanguageConstructSpacing |
Squiz.WhiteSpace.PropertyLabelSpacing |
(no replacement) |
Zend.Debug.CodeAnalyzer |
(no replacement) |
As of PHP_CodeSniffer 4.0, PHP_CodeSniffer will no longer throw warnings about potential parse errors. This was only done in a few places anyway, while the fast majority of sniffs would try to silently ignore code with parse errors.
Note
Results from PHP_CodeSniffer for code containing parse errors may not be correct or complete. It is strongly recommended to only run PHP_CodeSniffer on code which will compile without problems.
Search your [.]phpcs.xml[.dist]
file for the below error codes. If these error codes are referenced in a ruleset, you should remove them.
Search for and remove |
---|
Generic.Classes.OpeningBraceSameLine.MissingBrace |
Internal.ParseError.InterfaceHasMemberVar |
Internal.ParseError.EnumHasMemberVar |
PEAR.Classes.ClassDeclaration.MissingBrace |
Squiz.Classes.ValidClassName.MissingBrace |
Squiz.Commenting.ClosingDeclarationComment.Abstract |
Squiz.Commenting.ClosingDeclarationComment.MissingBrace |
Squiz.ControlStructures.ForEachLoopDeclaration.MissingOpenParenthesis |
Squiz.ControlStructures.ForEachLoopDeclaration.MissingCloseParenthesis |
Squiz.ControlStructures.ForEachLoopDeclaration.MissingAs |
Squiz.ControlStructures.ForLoopDeclaration.NoOpenBracket |
Squiz.ControlStructures.SwitchDeclaration.MissingColon |
Search your [.]phpcs.xml[.dist]
file for the below error codes. If these error codes are referenced in a ruleset, you should replace them.
Search for | Replace with |
---|---|
Generic.Formatting.MultipleStatementAlignment.IncorrectWarning |
Generic.Formatting.MultipleStatementAlignment.Incorrect |
Generic.Formatting.MultipleStatementAlignment.NotSameWarning |
Generic.Formatting.MultipleStatementAlignment.NotSame |
Squiz.Classes.ValidClassName.NotCamelCaps |
Squiz.Classes.ValidClassName.NotPascalCase |
Squiz.PHP.Heredoc.NotAllowed |
Squiz.PHP.Heredoc.HeredocNotAllowed and/or Squiz.PHP.Heredoc.NowdocNotAllowed
|
PSR12.Files.FileHeader.SpacingAfterBlock |
PSR12.Files.FileHeader.SpacingAfterTagBlock , PSR12.Files.FileHeader.SpacingAfterDocblockBlock , PSR12.Files.FileHeader.SpacingAfterDeclareBlock , PSR12.Files.FileHeader.SpacingAfterNamespaceBlock , PSR12.Files.FileHeader.SpacingAfterUseBlock , PSR12.Files.FileHeader.SpacingAfterUseFunctionBlock and/or PSR12.Files.FileHeader.SpacingAfterUseConstBlock
|
PSR12.Files.FileHeader.SpacingInsideBlock |
PSR12.Files.FileHeader.SpacingInsideUseBlock , PSR12.Files.FileHeader.SpacingInsideUseFunctionBlock and/or PSR12.Files.FileHeader.SpacingInsideUseConstBlock
|
Squiz.Commenting.VariableComment.TagNotAllowed |
Squiz.Commenting.VariableComment.[TagName]TagNotAllowed ([TagName] is dynamically generated based on the tags seen) |
The error
property has been removed from the following sniffs:
Generic.Strings.UnnecessaryStringConcat
Generic.Formatting.MultipleStatementAlignment
Search your [.]phpcs.xml[.dist]
file for the above mentioned sniffs and check if the error
property has been set. If so, remove it.
Changing the message type for messages from these sniffs is still possible by using <type>
instead, like so:
<rule ref="Generic.Strings.UnnecessaryStringConcat">
<type>warning</type>
</rule>
Tip
<type>
can also be set for individual error codes, not just for the complete sniff.
PHP_CodeSniffer 3.2.0 introduced a new ignore annotation syntax and deprecated the old syntax. Support for the old syntax has been removed in PHP_CodeSniffer 4.0.
This means that any code violations which were previously ignored using the old syntax, will now no longer be ignored.
If you haven't done so already, execute a search & replace on your code base.
Search for | Replace with |
---|---|
@codingStandardsIgnoreFile |
phpcs:ignoreFile |
@codingStandardsIgnoreStart |
phpcs:disable |
@codingStandardsIgnoreEnd |
phpcs:enable |
@codingStandardsIgnoreLine |
phpcs:ignore |
@codingStandardsChangeSetting |
phpcs:set |
Tip
While doing the search & replace, also update the ignore annotations to be selective to prevent them ignoring too much.
For more information about selectively ignoring parts of a file, see the Advanced Usage page and the PHP_CodeSniffer 3.2.0 release notes.
The exit codes used by PHP_CodeSniffer have changed. This change was made primarily to allow for phpcbf
to exit with a 0
exit code if all fixable issues were fixed and there are no non-auto-fixable issues remaining.
The pre-existing ignore_warnings_on_exit
and ignore_errors_on_exit
config flags will still be respected.
Additionally, you can now use the new ignore_non_auto_fixable_on_exit
config flag to ignore non-auto-fixable issues when the exit code is generated.
CI scripts or git pre-commit hooks may be checking explicitly for specific exit codes from PHP_CodeSniffer. If that's the case, these will need to be updated.
This change should make it more straight-forward to pipe output from PHP_CodeSniffer to a file.
In odd cases, automated scripts piping PHP_CodeSniffer output to file may need updating and/or can be simplified.
Previously, files without extension were always ignored. Now, files without extension can be scanned, providing they are explicitly requested to be scanned.
If you want to start scanning a file without extension add it in a <file>
directive in your ruleset, like so:
<file>file_without_extension</file>
Previously a ruleset could already "extend" an array property for a sniff set by another ruleset.
As of PHP_CodeSniffer 4.0, a ruleset can also "extend" the default value of an array property as set in the sniff itself.
The upside of this is, that if you want to default value + some extras, you no longer need to duplicate the default values from sniff array properties in your ruleset. The downside is, of course, that if the default value of the property in the sniff changes, your scans may start failing without warning.
Example of how to use this feature:
The current default value for the forbiddenFunctions
property for the Generic.PHP.ForbiddenFunctions
sniff is:
$forbiddenFunctions = [
'sizeof' => 'count',
'delete' => 'unset',
];
Previously, if you wanted to add to this default value, you would need to duplicate it and then add your own values:
<property name="forbiddenFunctions" type="array">
<!-- Original values -->
<element key="sizeof" value="count"/>
<element key="delete" value="unset"/>
<!-- Your own values -->
<element key="print" value="echo"/>
</property>
Now you can "inherit" the default value and add to it by using extend="true"
:
<property name="forbiddenFunctions" type="array" extend="true">
<element key="print" value="echo"/>
</property>
Between the extension filtering via --extensions=...
(CLI) / <arg name="extensions" value="..."/>
(ruleset), potential --ignore=...
(CLI) / <exclude-pattern>...
(ruleset) directives being followed, and potential --filter=...
directives, there are no files eligible for scanning.
Review your CLI command/ruleset to ensure these directives are set correctly.
For everyone
Introduction
Requirements
Usage
Advanced Usage
Reporting
Configuration Options
Fixing Errors Automatically
FAQ
For coding standard creators
About Standards for PHP_CodeSniffer
Annotated Ruleset
Customisable Sniff Properties
Version 4.0 Upgrade Guide
For sniff developers
Coding Standard Tutorial
Version 4.0 Upgrade Guide (Dev)
Version 3.0 Upgrade Guide
Version 1.3.0 Upgrade Guide