Releases: PHPCSStandards/PHP_CodeSniffer
Release list
4.0.4 - 2026-08-06
The 4.0.2 release, the 4.0.3 and the 4.0.4 release are 100% the same (aside from the version number), there was just a slight snafu in the release publication on GitHub (missing PHAR assets). Sorry for the confusion.
4.0.2 - 2026-08-06
This is a security release and all users are advised to update their install(s) as soon as possible.
The security issue only affects users of the Gitblame, Hgblame or Svnblame report(s).
Added
- Tokenizer support for the PHP 8.5
(void)cast. #1325
TheT_VOID_CASTtoken has been added to theTokens::CAST_TOKENSarray. suggestsection to thecomposer.jsonfile to inform users about the recommendediconvandpcntlPHP extensions. #1388- Thanks to Rodrigo Primo for the patch.
Changed
- Clarified that
libxmlis a required PHP extension. #1409 - Squiz.Scope.StaticThisUsage: the sniff will now also search for the use of
$thisin static closures. #1377 - The Generic.PHP.LowerCaseKeyword, Generic.WhiteSpace.LanguageConstructSpacing and Squiz.Functions.FunctionDeclarationArgumentSpacing sniffs no longer embed UTF-8 middot characters for spaces in error messages. #1379, #1389 Fixes Squiz/#2652.
- Thanks to Rodrigo Primo for the patches.
- PSR2.ControlStructures.SwitchDeclaration: the error message for the use of colon + curly braces (
WrongOpener*) has been made more informative. #1358. Fixes #1322.- Thanks to Sule-Balogun Olanrewaju for the patch.
- The error messages for the following sniffs have been improved by exposing more data placeholders:
PEAR.Functions.FunctionDeclaration#1445- The
CloseBracketLineerror message now exposes 1 data value (previously 0). - The
EmptyLineerror message now exposes 1 data value (previously 0). - The
Indenterror message now exposes 3 data values (previously 2). - These changes also affect the same error codes for the
PSR12.Classes.AnonClassDeclarationandSquiz.Functions.MultiLineFunctionDeclarationsniffs.
- The
PSR2.Classes.ClassDeclaration#1446- The
ExtendsLineandImplementsLineerror messages now expose 3 data values (previously 1). - The
SpaceBeforeExtendsandSpaceBeforeImplementserror messages now expose 2 data values (previously 1). - These changes also affect the same error codes for the
PSR12.Classes.AnonClassDeclarationandSquiz.Classes.ClassDeclarationsniffs.
- The
PSR2.ControlStructures.SwitchDeclaration#1447- The
defaultNotLowerandcaseNotLowererror messages now expose 3 data values (previously 2). - The
SpaceBeforeColonDEFAULTandSpaceBeforeColonCASEerror messages now expose 1 data value (previously 0). - The
BodyOnNextLineDEFAULTandBodyOnNextLineCASEerror messages now expose 1 data value (previously 0). - The
WrongOpenerdefaultandWrongOpenercaseerror messages now expose 1 data value (previously 0).
- The
Squiz.ControlStructures.SwitchDeclaration#1449- The
CaseNotLowerandDefaultNotLowererror messages now expose 3 data values (previously 2). - The
CaseIndentandDefaultIndenterror messages now expose 2 data values (previously 0). - The
SpaceBeforeColonCaseandSpaceBeforeColonDefaulterror messages now expose 1 data value (previously 0). - The
BreakIndenterror message now exposes 1 data value (previously 0). - The
SpacingAfterCaseandSpacingAfterDefaulterror messages now expose 1 data value (previously 0).
- The
Squiz.Functions.FunctionDeclarationArgumentSpacing#1452- The
SpaceBeforeEqualserror message now exposes 3 data values (previously 2). - The
SpaceAfterEqualserror message now exposes 3 data values (previously 2).
- The
Squiz.Functions.MultiLineFunctionDeclaration#1453- The
FirstParamSpacingandUseFirstParamSpacingerror messages now expose 1 data value (previously 0). - The
OneParamPerLineandUseOneParamPerLineerror messages now expose 1 data value (previously 0). - These changes also affect the same error codes for the
PSR12.Classes.AnonClassDeclarationsniff.
- The
- If you have customised the error messages of these sniffs, please review your ruleset after upgrading.
- Thanks to Zhang WenTao for these patches.
- The following sniff(s) have received efficiency improvements:
- PSR2.Classes.PropertyDeclaration
- Thanks to Jonathan Champ for the patch.
- The test suite is now more contributor friendly for contributors on MacOS. #1437
- Thanks to Sergei Morozov for the patch.
- Various housekeeping, including improvements to the tests and documentation.
- Thanks to Dan Wallis, Rodrigo Primo, Sergei Morozov and Juliette Reinders Folmer for their contributions.
Fixed
- SECURITY FIX: Running PHP_CodeSniffer over untrusted files, for example, in a CI pipeline that scans pull requests, or on a developer machine reviewing third-party code, could result in attacker-controlled shell commands being executed when the
Gitblame,HgblameorSvnblamereport(s) would process a file whose name contains shell metacharacters. #1473- Users using the default
Fullreport, or any of the other non-*blame reports, are not affected. - For more details, see the security advisory.
- Thanks go to Faze-up and Volker Dusch for responsibly disclosing the vulnerability.
- Additionally, thanks go to Volker Dusch, Rodrigo Primo, Dan Wallis and Juliette Reinders Folmer for creating and testing the fix.
- Users using the default
- Fixed bug #1320: Generic.Strings.UnnecessaryHeredoc: the fixer could incidentally change tab indentation to space indentation in select lines in the heredoc body.
- Fixed bug #1354: PSR12.Functions.ReturnTypeDeclaration: prevent an "Undefined array key" warning if the code under scan contains a parse error.
- Thanks to Dan Wallis for the patch.
- Fixed bug #1357: Squiz.Scope.StaticThisUsage: false positive for usage of
$thisin non-static closures nested in OO methods. - Fixed bug #1368: PEAR.Functions.FunctionDeclaration: the indentation for subsequent lines in multi-line block comments within a multi-line function signature, would be incorrectly determined, leading to false positives and resulting in a fixer conflict when running
phpcbf.- This also fixes, by extension, the same issue in the
Squiz.Functions.MultiLineFunctionDeclarationsniff.
- This also fixes, by extension, the same issue in the
- Fixed bug #1418: Tokenizer/PHP: tokenization of an inline else colon after an inline comment could fail and/or throw a "Trying to access array offset on null" warning.
- Thanks to Lazizbek Ergashev for the patch.
- Fixed bug #1435: Generic.Formatting.MultipleStatementAlignment would get into a fixer conflict for multiple assignments within a single statement spanning multiple lines.
- Same as when the statement would be single-line, alignment of subsequent assignment operators within the same multi-line statement will now be ignored.
- Thanks to Sergei Morozov for the patch.
- Fixed bug #1451: Tokenizer/PHP: prevent an "Undefined array key" warning during live coding when a file ends on the name in a constant declaration.
- Thanks to Lazizbek Ergashev and Sai Asish Y for the patch.
- Fixed bug #1463: Squiz.Functions.FunctionDuplicateArgument: prevent an "Undefined array key" PHP warning when the sniff encounters a function declaration without parentheses (parse error / live coding).
- Thanks to Rodrigo Primo for the patch.
Other
- The GPG signature for the PHAR files has been rotated. The new fingerprint is: 5CB4F778BF9BC4FB67AE511D96E91A992CF22FF4.
New Contributors
The PHP_CodeSniffer project is happy to welcome the following new contributors:
@bigdevlarry, @Faze-up, @jrchamp, @lazerg, @morozov, @ntdiary, @SAY-5
Statistics
Closed: 10 issues
Merged: 33 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!
3.13.6 - 2026-08-06
This is a security release and all users are advised to update their install(s) as soon as possible.
Changed
- Various housekeeping, including improvements to the tests and documentation.
- Thanks to Sergei Morozov and Juliette Reinders Folmer for their contributions.
Fixed
- SECURITY FIX: Running PHP_CodeSniffer over untrusted files, for example, in a CI pipeline that scans pull requests, or on a developer machine reviewing third-party code, could result in attacker-controlled shell commands being executed when the
Gitblame,HgblameorSvnblamereport(s) would process a file whose name contains shell metacharacters. #1473- Users using the default
Fullreport, or any of the other non-*blame reports, are not affected. - For more details, see the security advisory.
- Thanks go to Faze-up and Volker Dusch for responsibly disclosing the vulnerability.
- Additionally, thanks go to Volker Dusch, Rodrigo Primo, Dan Wallis and Juliette Reinders Folmer for creating and testing the fix.
- Users using the default
Other
- The GPG signature for the PHAR files has been rotated. The new fingerprint is: 5CB4F778BF9BC4FB67AE511D96E91A992CF22FF4.
Statistics
Closed: 0 issues
Merged: 46 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!
4.0.1 - 2025-11-10
This release includes all improvements and bugfixes from PHP_CodeSniffer 3.13.5.
Added
- Runtime support for PHP 8.5. All known PHP 8.5 deprecation notices have been fixed.
- Syntax support for new PHP 8.5 features will follow in a future release.
- If you find any PHP 8.5 deprecation notices which were missed, please report them.
Changed
- The Squiz.ControlStructures.SwitchDeclaration sniff will now flag a PHP close tag as a "wrong opener" and will auto-fix this by inserting a colon. #1316
- Various housekeeping, including improvements to the tests and documentation.
Fixed
- 4.x regression #1277: bring back whitespace tolerance in
phpcs:ignorecomma-separated rule reference lists.- Note: this bug did not affect
phpcs:disable/phpcs:enableignore annotations.
- Note: this bug did not affect
- Fixed bug #968: Generic.WhiteSpace.ScopeIndent was reporting false positives - and making incorrect fixes - for lines following a line containing an arrow function.
- Thanks to Soichi Sato for the patch.
- Fixed bug #1216: Tokenizer/PHP: added more defensive coding to prevent PHP 8.5 "Using null as an array offset" deprecation notices.
- Thanks to Andrew Lyons for the patch.
- Fixed bug #1279: Tokenizer/PHP: on PHP < 8.0, an unclosed attribute (parse error) could end up removing some tokens from the token stream.
- This could lead to false positives and false negative from sniffs, but could also lead to incorrect fixes being made mangling the file under scan.
- Fixed bug #1315: Squiz.ControlStructures.SwitchDeclaration: a number of the fixers would get into fixer conflicts with each other if the code under scan contained multiple statements on a line within a
switch.- The sniff will now forbid - and auto-fix - multiple statements on one line for
case/defaultand "case breaking" statements.
- The sniff will now forbid - and auto-fix - multiple statements on one line for
- Fixed bug #1316: Tokenizer/PHP: a PHP close tag after a
switchcase condition or after adefaultkeyword, was not regarded as a "scope_opener" for thecase/defaultbody. - Fixed bug #1316: PSR2.ControlStructures.SwitchDeclaration: the
WrongOpenererror is now also auto-fixable if the wrong opener is a PHP close tag. - Fixed bug #1316: Squiz.PHP.NonExecutableCode would throw false positives when code within a switch control structure would move in and out of PHP.
New Contributors
The PHP_CodeSniffer project is happy to welcome the following new contributors:
@andrewnicols, @Soh1121
Statistics
Closed: 2 issues
Merged: 8 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!
3.13.5 - 2025-11-04
Added
- Runtime support for PHP 8.5. All known PHP 8.5 deprecation notices have been fixed.
- Syntax support for new PHP 8.5 features will follow in a future release.
- If you find any PHP 8.5 deprecation notices which were missed, please report them.
Changed
- Various housekeeping, including improvements to the tests and documentation.
- Thanks to Rodrigo Primo and Juliette Reinders Folmer for their contributions.
Fixed
- Fixed bug #1216: Tokenizer/PHP: added more defensive coding to prevent PHP 8.5 "Using null as an array offset" deprecation notices.
- Thanks to Andrew Lyons for the patch.
- Fixed bug #1279: Tokenizer/PHP: on PHP < 8.0, an unclosed attribute (parse error) could end up removing some tokens from the token stream.
- This could lead to false positives and false negative from sniffs, but could also lead to incorrect fixes being made mangling the file under scan.
- Thanks to Juliette Reinders Folmer for the patch.
Other
- Please be aware that the
masterbranch has been renamed to3.xand the default branch has changed to the4.xbranch.- If you contribute to PHP_CodeSniffer, you will need to update your local git clone.
- If you develop against PHP_CodeSniffer and run your tests against dev branches of PHPCS, you will need to update your workflows.
New Contributors
The PHP_CodeSniffer project is happy to welcome the following new contributors:
@andrewnicols
Statistics
Closed: 2 issues
Merged: 36 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!
4.0.0 - 2025-09-16
This release contains breaking changes.
Upgrade guides for both ruleset maintainers/end-users, as well as for sniff developers and integrators, have been published to the Wiki.
You are strongly encouraged to read the upgrade guide applicable to your situation before upgrading.
This release includes all improvements and bugfixes from PHP_CodeSniffer 4.0.0-beta1, 4.0.0-RC1, 3.13.3 and 3.13.4.
Changed
- Tokenizer/PHP: fully qualified
exit/die/true/false/nullwill be tokenized as the keyword token and the token'content'will include the leading backslash. #1201 - Wherever possible based on the PHP 7.2 minimum version, parameter types have been added to all methods. #1237
- The supported PHPUnit version constraints have been updated to
^8.4.0 || ^9.3.4 || ^10.5.32 || 11.3.3 - 11.5.28 || ^11.5.31. #1247- External standards using the PHP_CodeSniffer native framework may need to update their own PHPUnit version constraints.
- Various housekeeping, including improvements to the tests and documentation.
Fixed
- Fixed bug #1082: new exit codes weren't applied when running
phpcbfon code provided via STDIN.- Thanks to Dan Wallis for the patch.
- Fixed bug #1172:
// phpcs:setfor inline array properties did not handle a single item array with the valuetrue,falseornullcorrectly. - Fixed bug #1174: progress bar wasn't showing files as fixed when running
phpcbfin parallel mode. - Fixed bug #1226: PHP 8.5 "Using null as an array offset" deprecation notice.
Other
- Please be aware that the
masterbranch has been renamed to3.xand the default branch has changed to the4.xbranch.- If you contribute to PHP_CodeSniffer, you will need to update your local git clone.
- If you develop against PHP_CodeSniffer and run your tests against dev branches of PHPCS, you will need to update your workflows.
Statistics
Closed: 5 issues
Merged: 35 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!
3.13.4 - 2025-09-05
Fixed
- Fixed bug #1213: ability to run tests for external standards using the PHPCS native test framework was broken.
- Thanks to Juliette Reinders Folmer for the patch.
- Fixed bug #1215: PHP 8.5 "Using null as an array offset" deprecation notices.
- Thanks to Juliette Reinders Folmer for the patch.
Statistics
Closed: 0 issues
Merged: 3 pull requests
If you like to stay informed about releases and more, follow @phpcs on Mastodon or @PHP_CodeSniffer on X.
Please consider funding the PHP_CodeSniffer project. If you already do so: thank you!
3.13.3 - 2025-09-04
Added
- Tokenizer support for PHP 8.4 dereferencing of new expressions without wrapping parentheses. #1160
- Thanks to Juliette Reinders Folmer for the patch.
- Tokenizer support for PHP 8.4
abstractproperties. #1183- The
File::getMemberProperties()method now also supportsabstractproperties through a newis_abstractarray index in the return value. #1184 - Additionally, the following sniffs have been updated to support
abstractproperties: - Thanks to Juliette Reinders Folmer for the patches
- The
- Tokenizer support for the PHP 8.4 "exit as a function call" change. #1201
- When
exit/dieis used as a fully qualified "function call", it will now be tokenized asT_NS_SEPARATOR+T_EXIT. - Additionally, the following sniff has been updated to handle fully qualified exit/die correctly:
- Squiz.PHP.NonExecutableCode
- Thanks to Juliette Reinders Folmer for the patches
- When
Changed
- Tokenizer/PHP: fully qualified
true/false/nullwill now be tokenized asT_NS_SEPARATOR+T_TRUE/T_FALSE/T_NULL. #1201- Previously, these were tokenized as
T_NS_SEPARATOR+T_STRING. - Additionally, the following sniffs have been updated to handle fully qualified true/false/null correctly:
- Generic.CodeAnalysis.UnconditionalIfStatement
- Generic.ControlStructures.DisallowYodaConditions
- PEAR.Functions.ValidDefaultValue
- Thanks to Juliette Reinders Folmer for the patches.
- Previously, these were tokenized as
- Generic.PHP.Syntax: the sniff is now able to scan input provided via STDIN on non-Windows OSes. #915
- Thanks to Rodrigo Primo for the patch.
- PSR2.ControlStructures.SwitchDeclaration: the
WrongOpener*error code is now auto-fixable if the identified "wrong opener" is a semi-colon. #1161- Thanks to Juliette Reinders Folmer for the patch.
- The PSR2.Classes.PropertyDeclaration will now check that the abstract modifier keyword is placed before a visibility keyword. #1188
- Errors will be reported via a new
AbstractAfterVisibilityerror code. - Thanks to Juliette Reinders Folmer for the patch.
- Errors will be reported via a new
- Various housekeeping, including improvements to the tests and documentation.
- Thanks to Bernhard Zwein, Rick Kerkhof, Rodrigo Primo and Juliette Reinders Folmer for their contributions.
Fixed
- Fixed bug #1112 :
--paralleloption fails if PHP_CodeSniffer is invoked via bash and the invokation creates a non-PHPCS-managed process.- Thanks to Rick Kerkhof for the patch.
- Fixed bug #1113 : fatal error when the specified "files to scan" would result in the same file being added multiple times to the queue.
- This error only occured when
--parallelscanning was enabled. - Thanks to Rodrigo Primo for the patch.
- This error only occured when
- Fixed bug #1154 : PEAR.WhiteSpace.ObjectOperatorIndent: false positive when checking multiple chained method calls in a multidimensional array.
- Thanks to Rodrigo Primo for the patch.
- Fixed bug #1193 : edge case inconsistency in how empty string array keys for sniff properties are handled.
- Thanks to Rodrigo Primo and Juliette Reinders Folmer for the patch.
- Fixed bug #1197 : Squiz.Commenting.FunctionComment: return types containing a class name with underscores would be truncated leading to incorrect results.
- Thanks to Juliette Reinders Folmer for the patch.
Other
- The Wiki documentation is now publicly editable. 🎉
- Update proposals can be submittted by opening a pull request in the PHPCSStandards/PHP_CodeSniffer-documentation repository.
Contributions welcome ! - Thanks to Anna Filina, Dan Wallis and Juliette Reinders Folmer for their work on getting this set up.
- Update proposals can be submittted by opening a pull request in the PHPCSStandards/PHP_CodeSniffer-documentation repository.
- The Phar website has had a facelift. #107
- Thanks to Bernhard Zwein for making this happen!
New Contributors
The PHP_CodeSniffer project is happy to welcome the following new contributors:
@benno5020, @NanoSector
Statistics
Closed: 11 issues
Merged: 40 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!
4.0.0RC1 - 2025-06-18
This release includes all improvements and bugfixes from PHP_CodeSniffer 4.0.0-beta1, 3.13.1 and 3.13.2.
Changed
- The error code
Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterVisbilityhas been changed toSquiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterVisibility. #1136 - The following sniff(s) have received efficiency improvements:
- Generic.ControlStructures.InlineControlStructure #880
- Thanks to Rodrigo Primo for the patch.
Fixed
- Fixed bug #3889 : A selective
phpcs:enablecould sometimes override a later selectivephpcs:ignore.- Thanks to Brad Jorsch for the patch
- Fixed bug #1128 : missing 'parenthesis_owner' index for T_FUNCTION token on PHP < 7.4 when function is named "fn".
Other
- The GPG signature for the PHAR files has been rotated. The new fingerprint is: D91D86963AF3A29B6520462297B02DD8E5071466.
Calling all testers!
Please help by testing the RC 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.
Statistics
Closed: 2 issues
Merged: 4 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!
3.13.2 - 2025-06-18
Changed
- The documentation for the following sniffs has been improved:
- Squiz.Classes.SelfMemberReference
- Thanks to Rodrigo Primo for the patch.
- Various housekeeping, including improvements to the tests and documentation.
- Thanks to Rodrigo Primo and Juliette Reinders Folmer for their contributions.
Fixed
- Fixed bug #1135 : Squiz.Functions.FunctionDeclarationArgumentSpacing: typo in new error code
SpacingAfterSetVis[i]bility.- Thanks to Juliette Reinders Folmer for the patch.
Statistics
Closed: 0 issues
Merged: 6 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!