Added
- Files without extension can now be scanned if the path is passed in directly. #2916
- Previously, files without extension would always be ignored.
- Now, files with no extension are checked if explicitly passed on the command line or specified in a ruleset.
- Files without extension will still be ignored when scanning directories recursively.
- Support for extending a default value for an array property on a sniff from an XML ruleset file. #15
- Previously, using
extend="true"on an property tag for setting an array value could already extend a property value set elsewhere in an (inluded) ruleset. - Now, you can also add to (extend) a default value as set on the sniff itself.
- Note: the property default value and the values set via the ruleset will be merged.
- This also means that for associative arrays, you can redefine the value for a particular array key.
- For numerically indexed arrays, this means the array will be renumbered. Keep this in mind if the numeric indexes hold meaning.
- Previously, using
- Added support for PHP 8.4 properties in interfaces to File::getMemberProperties(). #2455
- Note: properties in interfaces is not fully supported yet, it is just this one method which handles them correctly at this moment.
Tokens::NAME_TOKENScontaining an array with the tokens used for identifier names. #3041- New sniff
Generic.WhiteSpace.GotoTargetSpacingto enforce no space between the label of agototarget and the colon following it. #1026 - An error message is now displayed if no files were checked during a run. #1595
- This occurs when all of the specified files matched exclusion rules, or none matched filtering rules.
- An error will be shown when attempting to change an unchangable PHP ini setting using
-d option[=value]or via the ruleset with<ini name=...>. #416- Previously, this was silently ignored.
- Attempting to change non-existent ini settings (typo, extension not loaded) will continue to be silently ignored.
Changed
- The minimum required PHP version has changed from 5.4.0 to 7.2.0.
- The default coding standard has changed from
PEARtoPSR12. - Both
phpcsas well asphpcbfwill now exit with exit code 0 if no issues were found/remain after fixing. #184- Non auto-fixable issues can be ignored for the exit code determination by setting the new
ignore_non_auto_fixable_on_exitconfig flag to1. - For full details on the new exit codes, please refer to the Wiki "Advanced Usage" page.
- Non auto-fixable issues can be ignored for the exit code determination by setting the new
- Composer installs no longer include any test files. #1908
- The test framework files will still be included to allow for use by external standards.
- All status, debug, and progress output is now sent to STDERR instead of STDOUT. #1612
- Only report output now goes through STDOUT. As a result of this, piping output to a file will now only include report output.
- Pipe both STDERR and STDOUT to the same file to capture the entire output of the run.
- The
--report-filefunctionality remains untouched. - With this change in place, timing and memory consumption stats will now be displayed more often as this will no longer interfere with reports.
- Only report output now goes through STDOUT. As a result of this, piping output to a file will now only include report output.
- The
--extensionscommand line argument no longer accepts the tokenizer along with the extension. #2448- Previously, you would check
.modulefiles as PHP files using--extensions=module/php. - Now, you use
--extensions=module.
- Previously, you would check
- When processing rulesets,
<config>directives will be applied based on the nesting level of the ruleset. #2197- Previously, it was not possible to overrule a
<config>directive set in an included ruleset from the "root" ruleset. - Now,
<config>directives set in the "root" ruleset will always "win" over directives in included rulesets. - When two included rulesets at the same nesting level both set the same directive, the value from the last included ruleset "wins" (= same as before).
- Previously, it was not possible to overrule a
- When processing rulesets,
<arg>directives will be applied based on the nesting level of the ruleset. #2395, #2597, #2602- Previously, it was not possible to overrule a
<arg>directive set in an included ruleset from the "root" ruleset. - Now,
<arg>directives set in the "root" ruleset will always "win" over directives in included rulesets. - When two included rulesets at the same nesting level both set the same directive, the value from the first included ruleset "wins" (= same as before).
- Previously, it was not possible to overrule a
- Internal errors will no longer be suppressed when the
--sniffsCLI argument is used. #98 - The
File::getDeclarationName()method will no longer acceptT_ANON_CLASSorT_CLOSUREtokens. #3766- A
RuntimeExceptionwill be thrown if these tokens are passed.
- A
- The
File::getDeclarationName()method will now always return a string (or throw an Exception). #1007- Previously, the method would return
nullif the name could not be determined, like during live coding.
Now it will return an empty string in those situations.
- Previously, the method would return
- The
File::getMemberProperties()method will no longer add warnings about possible parse errors. #2455- This means the
Internal.ParseError.InterfaceHasMemberVarand theInternal.ParseError.EnumHasMemberVarerror codes have been removed. - The method will now throw a "$stackPtr is not a class member var"
RuntimeExceptionfor properties declared in enums (parse error). - Properties declared in interfaces will be analyzed like all other properties, as these are allowed since PHP 8.4.
- This means the
- None of the included sniffs will warn about possible parse errors any more. #2455
- This improves the experience when the file is being checked inside an editor during live coding.
- If you want to detect parse errors, use the
Generic.PHP.Syntaxsniff or a dedicated linter instead.
- The PEAR + PSR2 FunctionCallSignature sniffs will now also examine anonymous class instantiations with parameters. #47
- The error code
Squiz.Classes.ValidClassName.NotCamelCapshas been changed toSquiz.Classes.ValidClassName.NotPascalCase. #2046- This reflects that the sniff is actually checking for
ClassNameand notclassName.
- This reflects that the sniff is actually checking for
- The error code
Squiz.PHP.Heredoc.NotAllowedhas been replaced bySquiz.PHP.Heredoc.HeredocNotAllowedandSquiz.PHP.Heredoc.NowdocNotAllowed. #2318- This allows for forbidding either heredocs or nowdocs without forbidding both.
- The
PSR12.Files.FileHeadersniff now has more modular error codes to allow for more selectively applying the rules. #2729 #3453- The
PSR12.Files.FileHeader.SpacingAfterBlockerror code is replaced by:PSR12.Files.FileHeader.SpacingAfterTagBlockPSR12.Files.FileHeader.SpacingAfterDocblockBlockPSR12.Files.FileHeader.SpacingAfterDeclareBlockPSR12.Files.FileHeader.SpacingAfterNamespaceBlockPSR12.Files.FileHeader.SpacingAfterUseBlockPSR12.Files.FileHeader.SpacingAfterUseFunctionBlockPSR12.Files.FileHeader.SpacingAfterUseConstBlock
- The
PSR12.Files.FileHeader.SpacingInsideBlockerror code is replaced by:PSR12.Files.FileHeader.SpacingInsideUseBlockPSR12.Files.FileHeader.SpacingInsideUseFunctionBlockPSR12.Files.FileHeader.SpacingInsideUseConstBlock
- The
- The error code
Squiz.Commenting.VariableComment.TagNotAllowedhas been replaced by a dynamicSquiz.Commenting.VariableComment.[TagName]TagNotAllowederror code. #1039- This allows for selectively allowing specific tags by excluding the error code for that tag.
- Example: to allow
@linktags in property docblocks, exclude theSquiz.Commenting.VariableComment.LinkTagNotAllowederror code.
- The following sniffs have received performance related improvements:
- PEAR.NamingConventions.ValidVariableName
- PSR2.Classes.PropertyDeclaration
- Squiz.Commenting.VariableComment
- Squiz.Scope.MemberVarScope
- Squiz.WhiteSpace.MemberVarSpacing
- These sniffs will no longer listen to non-variable tokens, nor for variables tokens outside of OO context. #374
External sniffs which extend one of these sniffs may need adjustment if they want to retain the old behaviour.
- PHPCS now uses the PHP >= 8.0 native method for tokenizing (namespaced) identifier names. #3041
- Before PHP 8.0, PHP would tokenize namespaced names using
T_STRINGandT_NS_SEPARATOR. - From PHP 8.0, PHP uses the tokens
T_NAME_FULLY_QUALIFIED,T_NAME_RELATIVE, andT_NAME_QUALIFIEDinstead. - PHPCS now uses these new PHP 8.0 tokens no matter what version of PHP is being used to run PHPCS.
- Custom sniffs that use
T_STRINGandT_NS_SEPARATORtokens to look for namespaced names will need to be modified. - The
Tokens::FUNCTION_NAME_TOKENS/Tokens::$functionNameTokensarray now includes the identifier name tokens.
- Before PHP 8.0, PHP would tokenize namespaced names using
- Closure T_USE tokens, T_ISSET, T_UNSET, T_EMPTY, T_EVAL and T_EXIT tokens now contain parenthesis information. #23, #2593
- Previously, you had to find the opening and closing parenthesis by looking forward through the token stack.
- Now, you can use the
parenthesis_owner,parenthesis_openerandparenthesis_closerarray indexes.
- The
statickeyword when preceded byinstanceofwill now be tokenized (again) asT_STATIC. #22- Previously, the token was (re-)tokenized to
T_STRING.
- Previously, the token was (re-)tokenized to
T_OPEN_TAGtokens will no longer contain any whitespace. #593- Previously, "long" open tags could include either a single space or a new line character.
- This whitespace will now be tokenized as a
T_WHITESPACEtoken.
T_GOTO_LABELtokens will no longer include the colon following it. #185- The colon belonging with a goto label will now be tokenized separately as
T_GOTO_COLON.
- The colon belonging with a goto label will now be tokenized separately as
- Context sensitive keywords used as a label in a
gotostatement will now be tokenized asT_STRINGto prevent confusing sniffs. #185 - All
T_DOC_COMMENT_*tokens now have thecomment_openerandcomment_closerindexes set. #484 - The
Tokens::FUNCTION_NAME_TOKENS/Tokens::$functionNameTokensarray now includes theT_ANON_CLASStoken. #47 - Type casting for sniff property values set from within a ruleset has been made more consistent. #708
trueandfalsewill now always be set to a boolean value, independently of the case in which the value was provided.nullwill now be set to an actualnullvalue. Previously, the sniff property would have been set to string'null'.- Array element values will now also get the type casting treatment. Previously, array values would always be strings.
- The
PHP_CodeSniffer\Config::setConfigData()method is no longer static. #2675- The associated (
private)Config::$overriddenDefaultsproperty is also no longer static.
- The associated (
- The
PHP_CodeSniffer\Config::setSettings()method is now avoidmethod. #1001 - The signature of the
DummyFile::setErrorCounts()method has changed and now expects the following parameters:$errorCount, $warningCount, $fixableErrorCount, $fixableWarningCount, $fixedErrorCount, $fixedWarningCount. #1079 - The
Generatorclasses will now throw aPHP_CodeSniffer\Exceptions\GeneratorExceptionwhen encountering errors in the documentation XML. #1072 - The
PHP_CodeSniffer\Generators\HTML::STYLESHEET,PHP_CodeSniffer\Util\Timing::MINUTE_IN_MSandPHP_CodeSniffer\Util\Timing::SECOND_IN_MSclass constants are no longerpublic. #1051 - The
PHP_CodeSniffer\Util\Timingclass is nowfinaland marked as an internal class. #1074 - The Ruleset class no longer has special behaviour when used in a test context. #996
- The minimum required PHPUnit version for the test framework has changed from 4.0 to 8.0. #994, #997
- The test framework is now compatible with PHPUnit 8.x - 11.x (ignoring PHPUnit deprecations related to PHPUnit 12).
- The test framework has been refactored and no longer creates a custom test suite. #25
- If tests for an external standard extend the PHPCS native test suite, be sure to read the upgrade guide for more detail.
- The two abstract base test cases have been renamed. #25
- Replace
PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTestwithPHP_CodeSniffer\Tests\Standards\AbstractSniffTestCase. - Replace
PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTestwithPHP_CodeSniffer\Tests\Core\AbstractMethodTestCase.
- Replace
- Tests which extend the
AbstractSniffTestCasefor which no test case files (.incfiles) can be found, will now be marked as "incomplete". #998- Previously, those tests would silently pass.
- All test case files (
inc) which would be changed by the sniff under test if running the fixer, are now required to be accompanied by a*.fixedfile. #300
Deprecated
- The static token array properties in the
Tokensclass. Use the corresponding class constants on the Tokens class instead. #500 PHP_CodeSniffer\Util\Common::$allowedTypes. UsePHP_CodeSniffer\Util\Common::ALLOWED_TYPESinstead. #1043PHP_CodeSniffer\Tokenizers\PHP::$tstringContexts. UsePHP_CodeSniffer\Tokenizers\PHP::T_STRING_CONTEXTSinstead. #1043PHP_CodeSniffer\Sniffs\AbstractVariableSniff::$phpReservedVars. UsePHP_CodeSniffer\Sniffs\AbstractVariableSniff::PHP_RESERVED_VARSinstead. #1043PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff::$magicMethods. UsePHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff::MAGIC_METHODSinstead. #1043- This also affects the
PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniffclass which extends theCamelCapsFunctionNameSniff.
- This also affects the
PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff::$methodsDoubleUnderscore. UsePHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff::DOUBLE_UNDERSCORE_METHODSinstead. #1043- This also affects the
PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniffclass which extends theCamelCapsFunctionNameSniff.
- This also affects the
PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff::$magicFunctions. UsePHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff::MAGIC_FUNCTIONSinstead. #1043- This also affects the
PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniffclass which extends theCamelCapsFunctionNameSniff.
- This also affects the
PHP_CodeSniffer\Standards\Generic\Sniffs\Files\ByteOrderMarkSniff::$bomDefinitions. UsePHP_CodeSniffer\Standards\Generic\Sniffs\Files\ByteOrderMarkSniff::BOM_DEFINITIONSinstead. #1043PHP_CodeSniffer\Standards\Generic\Sniffs\Files\InlineHTMLSniff::$bomDefinitions. UsePHP_CodeSniffer\Standards\Generic\Sniffs\Files\InlineHTMLSniff::BOM_DEFINITIONSinstead. #1043PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\CharacterBeforePHPOpeningTagSniff::$bomDefinitions. UsePHP_CodeSniffer\Standards\Generic\Sniffs\PHP\CharacterBeforePHPOpeningTagSniff::BOM_DEFINITIONSinstead. #1043PHP_CodeSniffer\Standards\Generic\Sniffs\VersionControl\SubversionPropertiesSniff::$properties. UsePHP_CodeSniffer\Standards\Generic\Sniffs\VersionControl\SubversionPropertiesSniff::REQUIRED_PROPERTIESinstead. #1043PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FileCommentSniff::$tags. UsePHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FileCommentSniff::EXPECTED_TAGSinstead. #1043- This also affects the
PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\ClassCommentSniffclass which extends theFileCommentSniff.
- This also affects the
PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff::$magicMethods. UsePHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff::MAGIC_METHODSinstead. #1043- This also affects the
PHP_CodeSniffer\Standards\Squiz\Sniffs\NamingConventions\ValidFunctionNameSniffclass which extends the PEARValidFunctionNameSniff.
- This also affects the
PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff::$magicFunctions. UsePHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff::MAGIC_FUNCTIONSinstead. #1043- This also affects the
PHP_CodeSniffer\Standards\Squiz\Sniffs\NamingConventions\ValidFunctionNameSniffclass which extends the PEARValidFunctionNameSniff.
- This also affects the
PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\DisallowSizeFunctionsInLoopsSniff::$forbiddenFunctions. UsePHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\DisallowSizeFunctionsInLoopsSniff::FORBIDDEN_FUNCTIONSinstead. #1043PHP_CodeSniffer\Util\Standards::printInstalledStandards(). Useecho PHP_CodeSniffer\Util\Standards::prepareInstalledStandardsForDisplay()instead. #1054PHP_CodeSniffer\Config::printConfigData(). Useecho PHP_CodeSniffer\Config::prepareConfigDataForDisplay()instead. #1055- The
Reporter::$totalFixableandReporter::$totalFixedproperties. #1079- Use respectively
(Reporter::$totalFixableErrors + Reporter::$totalFixableWarnings)and(Reporter::$totalFixedErrors + Reporter::$totalFixedWarnings)instead.
- Use respectively
Removed
- Support for checking the coding standards of CSS and JS files has been removed. #2448
- Sniffs which are specifically aimed at CSS/JS files will no longer run.
- All other sniffs will now treat all files under scan as PHP files.
- The JS/CSS tokenizers and all tokens which were specifically for CSS/JS have also been removed.
- Support for sniffs not implementing the
PHP_CodeSniffer\Sniffs\Sniffinterface. See #694. - Support for sniffs not following the naming conventions. See #689.
- Support for external standards called "Internal". See #799.
- Support for the deprecated
@codingStandardannotation syntax has been removed. #1954- Use the
phpcs:or@phpcs:syntax instead- Replace
@codingStandardsIgnoreFilewithphpcs:ignoreFile - Replace
@codingStandardsIgnoreStartwithphpcs:disable - Replace
@codingStandardsIgnoreEndwithphpcs:enable - Replace
@codingStandardsIgnoreLinewithphpcs:ignore - Replace
@codingStandardsChangeSettingwithphpcs:set
- Replace
- Use the
- Support for the deprecated
ruleset.xmlarray property string-based syntax has been removed. #1983- Previously, an array value could be set using a comma-delimited string
print=>echo,create_function=>null - Now, individual array elements are specified using an
elementtag withkeyandvalueattributes- For example,
<element key="print" value="echo">
- For example,
- Previously, an array value could be set using a comma-delimited string
- The unused
T_ARRAY_HINTtoken. #1997 - The unused
T_RETURN_TYPEtoken. #1997 - The
Generic.Debug.ClosureLintersniff. #2448 - The
Generic.Debug.CSSLintsniff. #2448 - The
Generic.Debug.ESLintsniff. #2448 - The
Generic.Debug.JSHintsniff. #2448 - The
Generic.Formatting.NoSpaceAfterCastsniff. #2234- Use the
Generic.Formatting.SpaceAfterCastsniff instead with the$spacingproperty set to0.
- Use the
- The
Generic.Functions.CallTimePassByReferencesniff. #921 - The entire
MySourcestandard, and all sniffs within. #2471 - The
Squiz.Classes.DuplicatePropertysniff. #2448 - The entire
Squiz.CSScategory, and all sniffs within. #2448 - The
Squiz.Debug.JavaScriptLintsniff. #2448 - The
Squiz.Debug.JSLintsniff. #2448 - The
Squiz.Objects.DisallowObjectStringIndexsniff. #2448 - The
Squiz.Objects.ObjectMemberCommentsniff. #2448 - The
Squiz.WhiteSpace.LanguageConstructSpacingsniff. #1953- Use the
Generic.WhiteSpace.LanguageConstructSpacingsniff instead.
- Use the
- The
Squiz.WhiteSpace.PropertyLabelSpacingsniff. #2448 - The
Zend.Debug.CodeAnalyzersniff. #58 - The
errorproperty of sniffGeneric.Strings.UnnecessaryStringConcat. See #2823- This sniff now always produces errors
- To make this sniff produce warnings, include the following in a
ruleset.xmlor[.]phpcs.xml[.dist]file:<rule ref="Generic.Strings.UnnecessaryStringConcat"> <type>warning</type> </rule>
- The
errorproperty of sniffGeneric.Formatting.MultipleStatementAlignment. See #2823- This sniff now always produces warnings
- The
Generic.Formatting.MultipleStatementAlignment.IncorrectWarningerror code has been removed.- Refer to the
Generic.Formatting.MultipleStatementAlignment.Incorrecterror code instead.
- Refer to the
- The
Generic.Formatting.MultipleStatementAlignment.NotSameWarningerror code has been removed.- Refer to the
Generic.Formatting.MultipleStatementAlignment.NotSameerror code instead.
- Refer to the
- To make this sniff produce errors, include the following in a
ruleset.xmlor[.]phpcs.xml[.dist]file:<rule ref="Generic.Formatting.MultipleStatementAlignment"> <type>error</type> </rule>
- The
$ignoreCommentsparameter for theAbstractPatternSniff::__construct()method. - Ruleset::setSniffProperty(): support for the old
$settingsparameter format. #3629 - Use of the deprecated
auto_detect_line_endingsini setting. #3394- This removes support for files with
\rline endings.
- This removes support for files with
- The abstract
PHP_CodeSniffer\Filters\ExactMatch::getBlacklist()andPHP_CodeSniffer\Filters\ExactMatch::getWhitelist()methods. See #199.- These have been replaced by the
ExactMatch::getDisallowedFiles()andExactMatch::getAllowedFiles()methods.
- These have been replaced by the
- The deprecated
PHP_CodeSniffer\Generators\[HTML|Markdown|Text]::print*()methods. See #755. - Unused static
PHP_CodeSniffer\Reporter::$startTimeproperty. #1064
Fixed
- Fixed bug #185 : goto labels were incorrectly tokenized as
T_STRINGif there was whitespace and/or comments between the label and colon. - Fixed bug #1012 : in edge cases, the tokenizer could create some stray
parenthesis_*keys. - Fixed bug #1020 : File::findExtendedClassName() will no longer break on namespace relative class names.
- Fixed bug #1020 : File::findImplementedInterfaceNames() will no longer break on namespace relative interface names.
- Fixed bug #1020 : Various sniffs now have better support for ignoring/examining qualified function calls.
Other
Calling all testers!
Please help by testing the beta release and reporting any issues you run into.
Upgrade guides for both ruleset maintainers/end-users, as well as for sniff developers and integrators, have been published to the Wiki to help smooth the transition.
All patches courtesy of Greg Sherwood (@gsherwood) and Juliette Reinders Folmer (@jrfnl).
Special thanks go out to Dan Wallis (@fredden) and Rodrigo Primo (@rodrigoprimo) for their reviews and feedback.
Statistics
Closed: 51 issues
Merged: 95 pull requests
Follow @phpcs on Mastodon or @PHP_CodeSniffer on X to stay informed.
Please consider funding the PHP_CodeSniffer project. If you already do so: thank you!