Switching to the unified Magento Coding Standard




When working with Magento 2 depending on where you look there are different coding standards one might pick to follow:

  • PSR-2 (Magento is part of PHP-FIG after all)
  • MEQP-2 (Marketplace)
  • ECG-2 (Expert consulting group)
  • Standard contained in the Magento 2 code base

This is less than ideal and often leads to a situation of "do as we say, not do as we do" (not a big fan) or using a lowest denominator. Even ExtDN decided to jump into the mix to work out some workable compromise on the above.

I am pleased to see that Magento took the initiative and has been working on a unified standard that can be used across the entire Magento ecosystem. These efforts have been led by Lena Orobei and have resulted in the first releases of the Magento 2 Coding Standard.

There is of course always the danger of standard proliferation

Standard Proliferation

when introducing any new standard but I am confident this has a good chance of retiring all mentioned ones apart from PSR-2. What makes me hopeful is that any adopted rules are already run against the Magento 2 code base and issues are being identified and addressed as part of the rollout.

Getting started

So how do we get started? First we need to install the standard, which we can add as a development requirement to our project

composer require magento/magento-coding-standard:* --dev

From there we need to let PhpCodeSniffer (got automatically installed with the above) know about the new standard:

vendor/bin/phpcs --config-set installed_paths ../../magento/magento-coding-standard/

And from there we can use it against any code directory we want to statically test

vendor/bin/phpcs --standard=Magento2 src

and we will likely see a few things mentioned the first time we run it. Coding Standard Violations

From there we can hopefully work through these to remove them. Also take a look at running vendor/bin/phpcbf --standard=Magento2 src as that can automate some of the fixes.

There is more than 1 standard

I like to keep my code following PSR-2 as well. As that standard is one of the de-facto standards in the php world it comes pre-installed with PhpCodeSniffer and we can run it with

vendor/bin/phpcs --standard=PSR2 src

Working with Magento this will likely lead to some rule violations which we can't do much about (short of changing M2 whole sale, hello M1 legacy). Magento! In these cases code sniffer allows us to add exceptions via annotations or code comments.

    // phpcs:ignore PSR2.Methods.MethodDeclaration -- Magento 2 core use
    public function _toHtml()
    {
        if (!$this->getOptions()) {
            $this->setOptions($this->getColumns());
        }
        return parent::_toHtml();
    }

We should aim to adhere to the standard first before trying to exclude our code. Not all code is special and one should be prepared to provide a reason to add such an exception if this comes up in a code review. Also make the exclusion as specific and as narrow as possible, in other words you do not need to skip the whole file. If you need to find out the exact rule that triggered the warning you can run phpcs with the -s flag: vendor/bin/phpcs --standard=PSR2 src -s.

Automate it

One of the best ways to adopt a coding standard is to enforce it automatically when you check in any code. When working with git, git hooks are perfect for this. I have recently come across CaptainHook which makes configuring and sharing these hooks in your repository easier. Other tools like Grumphp can do the same for you. The aspect that appealed to me to start using CaptainHook is that I can keep the hook set up manual while I test out how this works for me before integrating this with Composer for all users as well.

composer require --dev captainhook/captainhook
vendor/bin/captainhook configure

Which will take you through a quick questionnaire. Alternatively you can supply a captainhook.json file in your root folder.

{
    "commit-msg": {
        "enabled": false,
        "actions": []
    },
    "pre-push": {
        "enabled": false,
        "actions": []
    },
    "pre-commit": {
        "enabled": true,
        "actions": [
            {
                "action": "\\CaptainHook\\App\\Hook\\PHP\\Action\\Linting",
                "options": [],
                "conditions": []
            },
            {
                "action": "vendor/bin/phpcs --config-set installed_paths ../../magento/magento-coding-standard/ && vendor/bin/phpcs --standard=Magento2 src",
                "options": [],
                "conditions": []
            }
        ]
    },
    "prepare-commit-msg": {
        "enabled": false,
        "actions": []
    },
    "post-commit": {
        "enabled": false,
        "actions": []
    },
    "post-merge": {
        "enabled": false,
        "actions": []
    },
    "post-checkout": {
        "enabled": false,
        "actions": []
    }
}

Which you can then activate with vendor/bin/captainhook install. From here on out any attempts to check in code with git commit that fails the php linting or Magento coding standard will get rejected, requiring you to apply a fix for it.

Changing to use the composer plugin instead will integrate with composer install or update and automate the hook activation composer require --dev captainhook/plugin-composer.

The standard is being collaboratively developed on github and you can check out its progress and underlying discussions here.

Kristof Ringleff

Kristof Ringleff

Founder and Lead Developer at Fooman

Join the Fooman Community

We send our popular Fooman Developer Monthly email with Magento news, articles & developer tips, as well as occasional Fooman extension updates.