Reducing command line args required for running PHPCS

Authored by

When you run JSHint, the only thing you need to put on the command line is: jshint. No additional arguments are required to check JS files under the current directory, and it automatically looks for a .jshintrc file for its configuration. For years now when I’ve wanted to similarly run PHP_CodeSniffer to check the adherence of some PHP code against coding standards, I’ve been running phpcs via:

phpcs --standard=phpcs.ruleset.xml -s --extensions=php .

There are here four additional arguments compared to what JSHint requires. The -s arg makes PHPCS show sniff codes in all reports (e.g. Squiz.Commenting.FileComment.SpacingAfterComment), something that is very helpful for figuring out which sniff is specifically being violated (so that it can potentially be excluded/suppressed in the project’s ruleset). The phpcs.ruleset.xml file here includes the WordPress-Core standard among other rules and configuration for the project. This file was named as such because originally PHP_CodeSniffer’s naming for ruleset files was an ambiguous “ruleset.xml”, and so it was first named in wp-dev-lib with the “phpcs.” prefix to make the filename more specific. The file was also then added to the plugin scaffolding command in WP-CLI. But recently Gary Jones pointed out:

what’s the reason for the naming as phpcs.ruleset.xml, instead of phpcs.xml.dist, as per the exact file in PHPCS, and in the documentation?

It turns out that in v2.2 PHP_CodeSniffer renamed the default ruleset file from ruleset.xml to phpcs.xml, and then in v2.5 it also added support for a phpcs.xml.dist fallback ruleset file, which aligns with PHPUnit’s default configuration files phpunit.xml and phpunit.xml.dist.

With the use of this PHPCS-recognized default ruleset file, this simplifies the above phpcs command down to:

phpcs -s --extensions=php .

Note that PhpStorm does not yet support auto-discovery of the phpcs.xml[.dist] files like it can for .eslintrc for ESLint or .jshintrc for JSHint. I’ve filed an issue to implement support for it. Once this lands in PhpStorm, it will greatly improve the experience of using the PHP_CodeSniffer inspection in the IDE when the opened project consists of an entire WordPress install with multiple themes and plugins each of which may have different PHPCS rulesets.

But wait, there’s more!

A couple days ago I was reviewing a pull request on Gutenberg which also sought to make it easier to invoke PHP_CodeSniffer on the project. We discovered that PHP_CodeSniffer allows you to define default command line args in the ruleset file. Thus the need to pass the --extensions=php -s args each time can be eliminated by amending the ruleset with:

<arg name="extensions" value="php"/>
<arg value="s"/>

And this further simplifies the command to:

phpcs .

But the command to run phpcs can be even shorter. The current directory “.” arg is being passed above because PHP_CodeSniffer will default to look at STDIN if no paths are passed in the command. This is different from JSHint which will assume you want to look for JS files in the current directory, and JSHint instead uses the common CLI idiom “-” to read from STDIN (though strangely ESLint does not also follow this convention). But, in the above Gutenberg PR, James Nylen noted use of the <file> to whitelist files and directories to check, and when this is in the ruleset then no paths need to be passed as args to phpcs. Well, the ruleset also has <exclude-pattern> defined then all that is really needed is for the ruleset to contain just “whitelist” one path, the current directory:

<file>.</file>
<exclude-pattern>*/node_modules/*</exclude-pattern>
<exclude-pattern>*/vendor/*</exclude-pattern>

And with that, all you need to run PHPCS is just:

phpcs

Support for these improvements has now been merged into wp-dev-lib. Additionally, I’ve opened a pull request for WP-CLI so that newly scaffolded projects can incorporate these improvements as well. I hope these changes improve your experience using PHP_CodeSniffer in your workflow.

4 thoughts on “Reducing command line args required for running PHPCS”

  1. I always think that it’s a good idea to use these with your IDE. So, that it can take you to the lines with the issue without having to search for it. With command line, it makes the task at hand quite tedious — just for PHPCS. How do you use it, Weston?

    1. @ahmad Yes, absolutely. PHPCS should indeed be set up to run automatically in the IDE, as it should also be set up to run in the pre-commit hook and in CI builds. I use PhpStorm and wp-dev-lib for those use cases. But sometimes I just need to run PHPCS from the command line. For example, wp-dev-lib by default has a CHECK_SCOPE=patches configuration which restricts reporting to just the lines changed in a commit or pull request. This is really useful when adding PHPCS to a preexisting project to avoid having thousands of errors screaming at you; I’ve proposed this for adding PHPCS to core in #34694. But if you do want to get a report on all of the PHPCS issues that should eventually get fixed in the project, you need to run PHPCS from the command line.

      Here’s what I’ve used to generate a report of all the PHPCS sniffs being violated in a codebase sorted by frequency:

      phpcs -s --extensions=php --report=emacs . | ack -o '(?<=\()\w+(\.\w+)+(?=\)$)' | sort | uniq -c | sort -nr

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.