Some developers wonder why it isn't enough that the code just works? The reason is that ugly code is doomed to lead to errors.
Published
Updated

git citool aftet phpcs run

Stylish code is in. All good developers care about how their code looks.

Some developers wonder why it isn’t enough that the code just works? The reason is that ugly code is doomed to lead to errors. Code that looks bad and sloppy is likely to be bad and sloppy. If the code is difficult to read, then it is more probable for bugs to remain unnoticed. When the ugly code is modified, it’s more likely that new errors will slip in. Reading and modifying ugly code takes more effort, and that energy and time is away from creative and thorough progress. One step forwards can easily become one step backwards. Every coder should strive to produce elegant code – both in form and function. If not, then the coder is too young or too careless to have responsibility over a production grade site.

The coding style should be uniform throughout the site. Different developers might have different preferences on what style is the best, but inside the same project developers must decide on common coding practices and everybody must follow the same style throughout the entire code base of that project (e.g. git repository).

For any WordPress plugin, theme or other WP projects the recommended coding style is what the WordPress core developers use themselves: the WordPress coding standards as defined in the WordPress Core developer handbook.

It covers all PHP, HTML, CSS and JavaScript. If you are new to these start by learning the WordPress PHP coding standards and PHP inline documentation standard.

Checking your code with PHPCS

There is a great tool to automate checking if the code follows a certain style or not. That tool is PHP Code Sniffer.

If you are using Seravo’s Vagrant or Docker development boxes, then PHPCS and the WordPress coding standard are already pre-installed. If you have your own development environment, you can install PHPCS for example with composer by running composer global require "squizlabs/php_codesniffer=*".

Basic documentation on how to use it can be found in the PHPCS wiki.

The WordPress coding standards can be found on GitHub in a machine readable format. There are certain parts of the standards that people refuse to follow in general, like the Yoda style comparisons and overly long indents. You can define your own PHP style as a subset of the WordPress style using a phpcs.xml ruleset file which you add to your project. There are many opinions here. The original PHP coding style and the WordPress coding style are different and don’t agree on all points. And it seems neither one is liked by developers, so different companies and projects end up doing their exceptions from the main rules. For examples check out Aucor’s Starter theme phpcs.xml or Geniem’s wp-project phpcs.xml.

Many Seravo projects include a phpcs.xml file like this:

<?xml version="1.0"?>
 <ruleset name="Seravo">
 <description>Seravo coding standards definition. Mostly WordPress coding standards, but relaxed a bit to be easier on developers.</description>

<arg value="p"/>

<file>htdocs/wp-content/themes/</file>

 <exclude-pattern>htdocs/index.php</exclude-pattern>
 <exclude-pattern>htdocs/wp-*.php</exclude-pattern>
 <exclude-pattern>htdocs/wordpress/*</exclude-pattern>
 <exclude-pattern>htdocs/wp-content/plugins/*</exclude-pattern>

 <rule ref="Squiz.PHP.CommentedOutCode"/>
 <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/>
 <rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/>
 <rule ref="Generic.Commenting.Todo"/>
 <rule ref="Generic.ControlStructures.InlineControlStructure"/>

 <rule ref="WordPress-Extra">
 <exclude name="Generic.WhiteSpace.DisallowSpaceIndent"/>
 <exclude name="Generic.WhiteSpace.ScopeIndent"/>
 <exclude name="PEAR.Functions.FunctionCallSignature.SpaceAfterOpenBracket" />
 <exclude name="PEAR.Functions.FunctionCallSignature.SpaceBeforeCloseBracket" />
 <exclude name="PEAR.Functions.FunctionCallSignature.Indent" />
 <exclude name="WordPress.WhiteSpace.PrecisionAlignment.Found" />
 <exclude name="WordPress.Arrays.ArrayDeclaration.IndexNoNewline" />
 <exclude name="WordPress.Arrays.ArrayKeySpacingRestrictions.NoSpacesAroundArrayKeys" />
 <exclude name="WordPress.PHP.YodaConditions" />
 </rule>
</ruleset>

By running phpcs -i you can verify that your PHPCS installation has the WordPress coding standard files available:

$ phpcs -i
The installed coding standards are WordPress-Docs, WordPress, 
PEAR, MySource, PSR1, WordPress-Extra, Security, WordPress-Core, 
Squiz, Zend, PHPCS, WordPress-VIP and PSR2

Running with phpcs -v launches the verbose mode, so you can verify that phpcs scans the correct files and uses sniffs from the correct standards:

$ phpcs -v
 Registering sniffs in the Seravo standard... DONE (63 sniffs registered)
 Creating file list... DONE (25 files in queue)
 Changing into directory /data/wordpress/htdocs/wp-content/themes/twentysixteen
 Processing rtl.css [CSS => 4527 tokens in 755 lines]... DONE in 1.64 secs (0 errors, 0 warnings)
 Changing into directory /data/wordpress/htdocs/wp-content/themes/twentysixteen/css
 Processing editor-style.css [CSS => 2752 tokens in 547 lines]... DONE in 1.01 secs (0 errors, 0 warnings)
 Processing ie.css [CSS => 249 tokens in 49 lines]... DONE in 213ms (0 errors, 0 warnings)
 Processing ie7.css [CSS => 944 tokens in 177 lines]... DONE in 467ms (0 errors, 0 warnings)
 Processing ie8.css [CSS => 1230 tokens in 223 lines]... DONE in 649ms (0 errors, 0 warnings)
 Changing into directory /data/wordpress/htdocs/wp-content/themes/twentysixteen/js
 Processing skip-link-focus-fix.js [JS => 340 tokens in 37 lines]... DONE in 361ms (2 errors, 0 warnings)
 Processing color-scheme-control.js [JS => 824 tokens in 97 lines]... DONE in 960ms (0 errors, 0 warnings)

$ phpcs -v test.php
 Registering sniffs in the Seravo standard... DONE (63 sniffs registered)
 Creating file list... DONE (1 files in queue)
 Changing into directory /data/wordpress/htdocs
 Processing test.php [PHP => 7811 tokens in 979 lines]... DONE in 5.94 secs (133 errors, 21 warnings)

FILE: /data/wordpress/htdocs/test.php
 ----------------------------------------------------------------------
 FOUND 133 ERRORS AND 21 WARNINGS AFFECTING 105 LINES
 ----------------------------------------------------------------------
 39 | ERROR | [x] Inline control structures are not allowed
 42 | ERROR | [x] Inline control structures are not allowed
 56 | ERROR | [x] Inline control structures are not allowed
 56 | WARNING | [ ] Not using strict comparison for in_array; supply
 | | true for third argument.
 70 | ERROR | [ ] Expected next thing to be an escaping function
 | | (see Codex for 'Data Validation'), not
 | | 'get_bloginfo'
 70 | ERROR | [ ] Expected next thing to be an escaping function
 | | (see Codex for 'Data Validation'), not
 | | '$separator'

Want colors? Try phpcs -v --colors *.php. Set colors on permanently with sudo phpcs --config-set colors 1.

If you get too many results, you may want to restrict PHPCS to only scan PHP files (yes, despite its name it by default also scans JavaScript and CSS files for style issues). Restrict the file types with --extensions=php. If you don’t want warnings included in the output, specify the -n command line argument. You can even further decrease the amount of output by using --report=summary to get a simple list of files and a count on how many errors and warnings they contained.

If you have a large project, you may want to have some progress reporting from phpcs so you can be sure it is actually running, because it may be silent for a long while before is prints out the results. To show progress status, specify -p on the command line or include in your phpcs.xml file the config  <arg value="p"/>.

$ phpcs -p
  ......................S..................................... 60 / 572
  ..........EEEE.E.E.E.E.E.E.E.E..W..EEE.E.E.E.EE.E.E.E.E.E.E. 120 / 572
  E.E.E.E.E.WWWW.E.W..EEE.E.................E.E.E.E...E....... 180 / 572

To be very very verbose on what files are scanned, what is the ugly code found and how it is corrected use the diff mode:

$ phpcs --report=diff testi.php
--- test.php
  +++ PHP_CodeSniffer
  @@ -36,11 +36,13 @@
  // Don't index any of these forms
  add_action( 'login_head', 'wp_no_robots' );

- if ( wp_is_mobile() )
  + if ( wp_is_mobile() ) {
  add_action( 'login_head', 'wp_login_viewport_meta' );
  + }

- if ( empty($wp_error) )
  + if ( empty($wp_error) ) {
  $wp_error = new WP_Error();
  + }

Automatic styling with PHPCBF

As you can see above, PHPCS not only knows what is ugly, but it also knows what the correct style should be. Well guess what? You can make PHPCS clean up (most of) the code for you in a fully automatic fashion! To do that, use the command phpcbf:

$ phpcbf testi.php
  Changing into directory /data/wordpress/htdocs
  Processing testi.php [PHP => 7811 tokens in 979 lines]... DONE in 5.76 secs (85 fixable violations)
  => Fixing file: 0/85 violations remaining [made 3 passes]... DONE in 18.34 secs
  E

Patched 1 file
  Time: 24.98 secs; Memory: 18Mb

Remember to review all changes an selectively pick the hunks and lines you actually want to have. An excellent tool for that is git citool.

Integrate in editor and CI

What if running PHPCS to check you style would be automatic, so that you don’t need to remember to do it? Well, many code editors integrate PHPCS and can give PHP style feedback in real-time.

You can also have a local git hook, that runs PHPCS on the files you are about to commit. Below is an example of a .git/hooks/pre-recieve hook script that automatically runs PHPCS and all the files that you are about to commit:

# Loop all files that are about to be committed (diff of git head and staged)
echo "==> Checking syntax errors..."
for FILE in $(git diff --cached --name-only); do
  resource="$REPO_DIR/$FILE"
  ##
  # Test PHP syntax for all changed *.php and *.module files
  ##
  if [[ "$FILE" =~ ^.+(php|module)$ ]]; then
    if [[ -f $resource ]]; then
      phpcs "$resource" 1> /dev/null
      if [ $? -ne 0 ]; then
        errors+=("PHP syntax Error: $FILE")
      fi
    fi
  fi
done

You can also integrate PHPCS into your CI-pipeline. The WordPress Coding Standards page has an example configuration for Travis-CI.

Seravo Plugin Travis-CI page

Security

The coding standards used by PHPCS, also called sniffs, are quite flexible. They can also be used for static code analysis of PHP to find potential security bugs.

$ phpcs --standard=Security .
  FILE: ...content/plugins/google-analytics-dashboard-for-wp/tools/gapi.php
  ----------------------------------------------------------------------
  FOUND 1 ERROR AND 8 WARNINGS AFFECTING 8 LINES
  ----------------------------------------------------------------------
  35 | WARNING | Possible RFI detected with GADWP_DIR on include_once
  51 | WARNING | Function array_map() that supports callback detected
  148 | WARNING | Possible XSS detected with esc_url on echo
  148 | ERROR | Easy XSS detected because of direct user input with
  | | $_SERVER on echo
  152 | WARNING | Possible XSS detected with __ on echo
  156 | WARNING | Possible XSS detected with _e on echo
  307 | WARNING | Crypto function crc32 used.
  425 | WARNING | Function array_map() that supports callback detected
  767 | WARNING | Function array_map() that supports callback detected
  ----------------------------------------------------------------------

No excuse to not use it

PHPCS is a mature style checker that will help you improve your code. It accelerates the velocity of development when multiple developers will be able to easily write consistent code with better quality and security. Less time will be spent hunting and fixing bugs. It is easy to do your own ruleset, so you can stick to the style you already use, but do it properly and consistently. If you think your project is somehow special and unfit for PHPCS, there is a big chance that the documentation on advanced use cases covers your project’s situation as well. There is really no excuse to not use PHPCS if you develop with PHP.

Now go on and install it, run phpcbf to automatically fix most of your existing issues, fix the rest manually and then make sure you have PHPCS in your editor, or run it before every git commit and enforce it in the continuous integration pipeline. Be a good person and keep your quality standards high!