Legacy PHP Application: PHP CS Fixer & PHP Code Sniffer for PSR1 & PSR2

Part 1 of this series covers a tour of my 14+ year old legacy CMS called LampLight and it continues with my use of command line code analysis tools to migrate it from PHP v 5.6 to 7.3. In this part we’ll continue to use PHP CS Fixer to clean up the code, and will then move on to use PHP Code Sniffer for even more tidying.

My last few uses of PHP Coding Standards Fixer, are to check for PSR1 and PSR2 compliance. These PSRs cover a baseline of code style conventions common among PHP projects.

Note that PHP CS Fixer provides rulesets for these PSRs, but they do not cover ALL of the rules found in the PSRs. For now I’ll just start with these, since it’s an easy process and a discontinued project.

First, running the ruleset for PSR1:

php-cs-fixer fix . --rules=@PSR1 --verbose --using-cache=no --dry-run

Actually reveals no issues! This is because I fixed the line ending problem when I migrated this project from Mercurial to Git. And the opening tags issue was solved in part 1 of this series. Well that was easy. So on to PSR2:

PHP CS Fixer and PSR2

php-cs-fixer fix . --rules=@PSR2 --verbose --using-cache=no --dry-run

This run however, reveals a TON of problems, in almost every file! Eeek!

There’s no way I want to either automatically fix this many issues at once, or try to pick my way through each one. So, I’ll use this output to pick out one rule at a time and run only that. Look it up to see what’s involved and if it looks straightforward I’ll let the fixer do it’s thing and then test. When I’m happy I’ll git commit to checkpoint my changes. This way I’ll work my way through all the rules covered by the @PSR2 ruleset.

You’ll notice that many of these rules deal with how whitespace is handled. This means there is very little risk in letting the fixer correct these automatically.

This process worked well and problem-free for each of these rules:

  • no_trailing_whitespace
  • no_trailing_whitespace_in_comment
  • single_blank_line_at_eof
  • indentation_type
  • method_argument_space
  • braces
  • function_declaration
  • no_spaces_inside_parenthesis
  • no_spaces_after_function_name
  • line_ending
  • lowercase_keywords
  • lowercase_constants

And these were all of the PSR2 rules that were flagged for my project. Turns out that I had no issues with any of these, and could have run the entire ruleset automatically.

One odd thing that kept creeping up is that the line endings kept having to be re-fixed on several files. Not sure what went on there. But it seems to have finally stayed fixed.

For the purposes of this project, this is it for what I wanted to do with PHP CS Fixer. Let’s move on to another awesome tool for PHP code analysis.

PHP Code Sniffer

PHP Code Sniffer aka PHP_CodeSniffer is another command line tool you can use to analyze your code based on various standards. On my legacy applications like this one, it flags a TON of issues. For this case, I’m only interested in checking for problems with the current version of PHP or future deprecations.

This is where the PHPCompatibility standard for PHP_CodeSniffer comes into play. But first, just for fun, let’s see if PHP_CodeSniffer picks up any PSR2 violations that PHP CS Fixer missed. Use the -s flag to make sure that each error also indicates which sniff was violated.

phpcs --standard=PSR2 -s .

Woah! This tool finds many things not covered by PHP CS Fixer! From the output we can see that all items marked with an [x] can be fixed automatically if we change to the bundled tool phpcbf. In my terminal PHP_CodeSniffer has reported pages upon pages of violations. Here are just a few:

We can break down which ‘sniffs’ are in a given standard with the following command:

phpcs --standard=PSR2 -e

Using this list, I can run PHP_CodeSniffer on a single rule or ‘sniff’. And begin to break down that giant list of violations into only the ones I want to fix. Here’s the spaces instead of tabs one:

phpcs --sniffs=Generic.WhiteSpace.DisallowTabIndent -s .

The included tool PHP Code Beautifier and Fixer aka Phpcbf can be used to fix these automatically. In most cases just replace the command name and it will work. First I’ll git commit my work up to now and give it a try:

phpcbf --sniffs=Generic.WhiteSpace.DisallowTabIndent .

Wow, this fixed 77 files for me! I’ll do the same routine with only the few things I want PHP_CodeSniffer to deal with. I could spend way more time on this given how many errors PHP_CodeSniffer found, but again this is a discontinued project and I don’t want to spend too much time. So I limit my fixes to:

phpcbf --sniffs=Generic.WhiteSpace.DisallowTabIndent .

phpcbf --sniffs=Generic.Functions.FunctionCallArgumentSpacing .

phpcbf --standard=Squiz --sniffs=Squiz.Functions.FunctionDeclarationArgumentSpacing .

A few gotchas popped up during this process. To fix a specific sniff you must also specify the standard that sniff is found in. Also, in your output with the -s flag, you’ll see it says something like:

Squiz.Functions.FunctionDeclarationArgumentSpacing.SpaceBeforeEquals

But the last part of this is a rule inside of the sniff. So I had to remove the .SpaceBeforeEquals part to make sure it matches the actual containing sniff.

This process required frequent reference to the output of phpcs --standard=PSR2 -e, which I eventually just ran in another terminal panel.

After a few of these individual sniffs were fixed I was losing track of where I was in relation to what PHP_CodeSniffer originally found. I wanted a more high-level view of what PHP_CodeSniffer is finding. To do so, I can specify a different report type:

phpcs --standard=PSR2 --report=source -s .

Oy. I have to admit that at this stage of the process, the thought of tracking down each of these sniffs and fixing each one and testing it… just didn’t seem worth it to me for rules that are largely stylistic in nature and for a discontinued project. So this is where I stopped with the PSR2 checks with PHP_CodeSniffer. I think this gives you, dear reader, enough of a handle on how to use this tool for these types of fixes.

I get the impression that PHP_CodeSniffer is more powerful than PHP CS Fixer for these style-based PSR checks.

What I really want to do, is address issues that actually affect my application running on PHP version 7.3 (and future versions). So in the next part of this series, I’ll move on to using PHP_CodeSniffer to run sniffs in the PHPCompatibility standard, which will find real issues that need to be addressed.

Leave a Reply

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

13 + one =