Magento 2 Coding Standard Best Practices

| |
Comments: 0

Magento 2 is a leading e-Commerce Platform. Every retail business from small to large scale wanted to use such a leading platform. Magento Framework provides a number of stores, can manage various payment methods, shipping methods, and enhances performance using third-party extensions.

While using a third-party extension, there are pre-defined coding standards which needs to be followed by the developers. Magento 2 coding standard is used to improve code quality and maintaining interoperability with Magento source code.

Sometimes developers work under short deadlines, and they are not able to maintain coding standards. Quality of code surely affects the performance of code. There are several tools available that automatically checks the Coding Standard of custom modules.

Magento also provides Magento Coding Standard tool which tests Magento code and also includes standards of PHP code Sniffer, PHP Mess-Detector, GrumPHP, PHP Code Beautifier and fixer, and PSR.

What is PHP Code Sniffer (phpcs)?

  • PHP Code Sniffer tool is sniffing PHP code, JavaScript code and CSS code.
  • Developer can check coding standard in command prompt with the below command:
vendor/bin/phpcs –standard=PSR1, Magento2 –severity=10 [path to Magento module]
  • Developers can also check other Standards like PSR2, PSR12, PEAR, Squiz, Zend, Magento2Framework, and PHPCompatibility.
  • PSR (PHP Standard Recommendation) Standards helps to Standardize PHP code. Like PSR1 checks Basic Coding Standards, PSR2 checks Coding Style.
  • As shown above, those errors and warnings violates PHP Code Sniffer Standards.
  • PHP Code Beautifier and Fixer (phpcbf) tool can fix violations (e.g, blank spaces or blank lines and beautify code.)
vendor/bin/phpcbf –standard=Squiz [path to Magento module]
Things consider while hiring developer

What is PHP Mess-Detector (phpmd)?

PHP Mess-Detector also known as phpmd which checks the complexity of code, checks how variables are used in code, and phpmd can detect some unused code.

Magento also provides phpmd tool. By using phpmd, developers can check coding standards of code.

For that, you have to run below command.

vendor/bin/phpmd [path to Magento module] format ruleset

In the above command,

format argument is used to display instructions or warnings in below formats ansi, baseline, checkstyle, github, html, json, sarif, text, xml

For the ruleset argument, these default formats are available: cleancode, codesize, controversial, design, naming, unusedcode.

Things consider while hiring developer
  • unusedcode ruleset will detect unused code in your module.
  • naming ruleset will detect variables and methods whose names are not matching standards.
  • codesize ruleset will detect Cyclomatic Complexity, NPath complexity in code.

What is GrumPHP tool?

GrumPHP checks Coding Standards while developers doing git commits. In GrumPHP 5 to 6 Coding Standards will be checked. Sometimes manually checking those standards will be a very tedious process. When GrumPHP installed in your environment, developer will not be able to commit code unless all coding standards will be fulfilled.

To setup GrumPHP use below commands.

composer require –dev phpro/grumphp

Run above command in root directory of your project.

To setup GrumPHP globally run below command.

composer global require –dev phpro/grumphp

If you are facing laminas-dependency-plugin version issue, then run below commands.

sudo composer require laminas/laminas-dependency-plugin:2.2.0
sudo composer require –dev phpro/grumphp:* -W

To setup dependencies of GrumPHP follow below steps.

1. PHPCS

composer global require –dev “squizlabs/php_codesniffer=*” (globally recommended)
composer require –dev “squizlabs/php_codesniffer=*” (at project level, need to add project-root/vendor/bin to PATH for direct cli use)

2. PHPCSFixer2

composer global require –dev friendsofphp/php-cs-fixer (globally recommended)
composer require –dev friendsofphp/php-cs-fixer (at project level, need to add project-root/vendor/bin to PATH for direct cli use)

3. PHPStan

composer global require –dev phpstan/phpstan (globally recommended)
composer require –dev phpstan/phpstan (at project level, need to add project-root/vendor/bin to PATH for direct cli use)

4. PHPMD

composer global require –dev phpmd/phpmd (globally recommended)
composer require –dev phpmd/phpmd (at project level, need to add project-root/vendor/bin to PATH for direct cli use)

5. PHPLint

composer global require –dev php-parallel-lint/php-parallel-lint (globally recommended)
composer require –dev php-parallel-lint/php-parallel-lint (at project level, need to add project-root/vendor/bin to PATH for direct cli use)

GrumPHP will sniff your commits by initializing it in the repository. GrumPHP can be setup in two ways Root level and Module level.

php vendor/bin/grumphp git:init

Run the above command to init grumphp

  • To setup Root level create grumphp.yml (as shown below) file in root directory.
  • To setup at Module level create grumphp.yml (as shown below) file in magento-2-root/app/code/MyVendor/MyModule directory.

After that you have to add bin path to your composer.json file.

{
“config”: {
“bin-dir”: “../../../../vendor/bin”
}
}

Create grumphp.yml file and put below code in that file for Root Level Setup.

grumphp:
hide_circumvention_tip: true
process_timeout: 120
stop_on_failure: false
ignore_unstaged_changes: false
tasks:
jsonlint:
detect_key_conflicts: true
metadata:
priority: 100
xmllint:
ignore_patterns:
– “#test/(.*).xml#”
metadata:
priority: 100
phplint:
triggered_by: [‘php’, ‘phtml’]
metadata:
priority: 200
yamllint:
ignore_patterns:
– “#test/(.*).yml#”
– “#charts/.*#”
metadata:
priority: 100
composer:
file: ./composer.json
no_check_all: true
no_check_lock: false
no_check_publish: false
with_dependencies: false
strict: false
metadata:
priority: 80
# validate git commit message
git_commit_message:
allow_empty_message: false
enforce_capitalized_subject: false
enforce_no_subject_punctuations: false
enforce_no_subject_trailing_period: true
enforce_single_lined_subject: true
type_scope_conventions: []
max_body_width: 80
max_subject_width: 80
matchers:
“Commit message must contain issue topic and number”: /^\[(HOTFIX|BUGFIX|FEATURE|INF
RA|MERGE|RELEASE)]\sICRSICRP-\d+\s::\s.*\s\[(COMPLETED|WIP)]/ case_insensitive: true
multiline: false
additional_modifiers: ”
# validate git branch names
git_branch_name:
whitelist:
# allowed branch names: ‘feature-1’, ‘feature-new’, ‘feature-new1’, ‘task-1’, etc
– “/(hotfix|bugfix|feature|release|task)-([a-z|0-9]+)$/”
blacklist:
– “development”
– “production”
– “staging”
– “master”
– “infra”
allow_detached_head: true
# catch not allowed keywords
git_blacklist:
keywords:
– “\\.dev”
– “\\.local”
– “\\.test”
– “<<<<<<<“
– “=======”
– “DebuggerUtility”
– “ObjectManager::getInstance”
– “_GET\\[“
– “_POST\\[“
– “_REQUEST\\[“
– “console.log(“
– “die(“
– “die;”
– “exit(“
– “exit;”
– “fileadmin”
– “localhost”
– “phpinfo”
– “phpinfo(“
– “print_r(“
– “var_dump(“
– “_objectManager”
– “ObjectManagerInterface”
triggered_by: [‘php’, ‘js’, ‘html’, ‘phtml’]
metadata:
priority: 90
# https://devdocs.magento.com/guides/v2.4/coding-standards/code-standard-php.html
phpcs:
standard: Magento2
tab_width: 4
severity: 10 # can remove this to dis allow all level of severity.
error_severity: 10
warning_severity: ~
report: full
triggered_by: [phtml, php]
metadata:
priority: 70
phpcsfixer2:
allow_risky: false
config: ‘.php_cs.dist’
triggered_by: [‘php’, ‘phtml’]
using_cache: true
cache_file: ‘./.php_cs.cache’
config_contains_finder: true
verbose: true
phpmd:
ruleset: [‘./dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml’]
triggered_by: [‘php’]
exclude:
– “./app/code/Magento/”
– “./app/code/*/*/Setup/”
metadata:
priority: 70
# uncomment to skip modules using whitelist patterns
# whitelist_patterns:
# – /^app\/code\/MyVendor\/MyModuleToSkip\/(.*)/
# https://devdocs.magento.com/guides/v2.4/test/testing.html#phpstan
phpstan:
autoload_file: ~
configuration: ‘./dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/
phpstan.neon’
level: 8
triggered_by: [‘php’]
force_patterns: []
ignore_patterns: []
memory_limit: “-1”
metadata:
priority: 90
phpversion:
Project: ‘8.1.*’

Create grumphp.yml file and put below code in that file for Module Level Setup.

grumphp:
hide_circumvention_tip: true
process_timeout: 120
stop_on_failure: false
ignore_unstaged_changes: false
tasks:
jsonlint:
detect_key_conflicts: true
metadata:
priority: 100
xmllint:
ignore_patterns:
– “#test/(.*).xml#”
metadata:
priority: 100
phplint:
triggered_by: [‘php’, ‘phtml’]
metadata:
priority: 200
yamllint:
ignore_patterns:
– “#test/(.*).yml#”
– “#charts/.*#”
metadata:
priority: 100
composer:
file: ./composer.json
no_check_all: true
no_check_lock: false
no_check_publish: false
with_dependencies: false
strict: false
metadata:
priority: 80
# validate git commit message
git_commit_message:
allow_empty_message: false
enforce_capitalized_subject: false
enforce_no_subject_punctuations: false
enforce_no_subject_trailing_period: true
enforce_single_lined_subject: true
type_scope_conventions: []
max_body_width: 80
max_subject_width: 80
matchers:
“Commit message must contain issue topic and number”: /^\[(HOTFIX|BUGFIX|FEATURE|INFRA|MERGE|RELEASE)]\sICRSICRP-\d+\s::\s.*\s\[(COMPLETED|WIP)]/
case_insensitive: true
multiline: false
additional_modifiers: ”
# validate git branch names
git_branch_name:
whitelist:
# allowed branch names: ‘feature-1’, ‘feature-new’, ‘feature-new1’, ‘task-1’, etc – “/(hotfix|bugfix|feature|release|task)-([a-z|0-9]+)$/”
blacklist:
– “development”
– “production”
– “staging”
– “master”
– “infra”
allow_detached_head: true
# catch not allowed keywords
git_blacklist:
keywords:
– “\\.dev”
– “\\.local”
– “\\.test”
– “<<<<<<<“
– “=======”
– “DebuggerUtility”
– “ObjectManager::getInstance”
– “_GET\\[“
– “_POST\\[“
– “_REQUEST\\[“
– “console.log(“
– “die(“
– “die;”
– “exit(“
– “exit;”
– “fileadmin”
– “localhost”
– “phpinfo”
– “phpinfo(“
– “print_r(“
– “var_dump(“
– “_objectManager”
– “ObjectManagerInterface”
triggered_by: [‘php’, ‘js’, ‘html’, ‘phtml’]
metadata:
priority: 90
# https://devdocs.magento.com/guides/v2.4/coding-standards/code-standard-php.html phpcs:
standard: Magento2
tab_width: 4
severity: 10 # can remove this to dis allow all level of severity.
error_severity: 10
warning_severity: ~
report: full
triggered_by: [phtml, php]
metadata:
priority: 70
phpcsfixer2:
allow_risky: false
Config: ‘../../../../.php_cs.dist’
triggered_by: [‘php’, ‘phtml’]
using_cache: true
cache_file: ‘./.php_cs.cache’
config_contains_finder: false
verbose: true
phpmd:
Ruleset: [‘../../../../dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/
ruleset.xml’]
triggered_by: [‘php’]
exclude:
– “./app/code/Magento/”
– “./app/code/*/*/Setup/”
metadata:
priority: 70
# uncomment to skip modules using whitelist patterns
# whitelist_patterns:
# – /^app\/code\/MyVendor\/MyModuleToSkip\/(.*)/
# https://devdocs.magento.com/guides/v2.4/test/testing.html#phpstan
phpstan:
autoload_file: ~
Configuration: ‘../../../../dev/tests/static/testsuite/Magento/Test/Php/
_files/phpstan/phpstan.neon’
level: 8
triggered_by: [‘php’]
force_patterns: []
ignore_patterns: []
memory_limit: “-1”
metadata: priority: 90
phpversion: Project: ‘8.1.*’

Key points developers need to take care of for coding purposes

Writing Clean Code by Reducing Code Redundancy

It is found that many developers write the same code for the same functionality many times. This, in reality, increases code redundancy, and eventually, the code size gets larger due to the use of many redundant codes. One can write a function or class containing the redundant code and use it when it is required, this will lead to very helpful maintaining the code because you don’t have to change the code at all the places where you have used you need to modify a function or class and this also come under coding standards of writing clean code.

We can also make our code look good and increase its uses by writing generic code. It has been noticed that developers write code specific to the functionality but when you take a closer look into the code an intelligent developer can see that the code can be refactored and put into a function or a class and can be used wherever it is needed.

Caching a crucial functionality

Caching is one of the crucial functionality Magento offers. It speeds up the site by loading content from the cache and there is some instance that it can cache the whole page. But it also has some cons, if a developer doesn’t know this or maybe forgot to clean the cache then it can create confusion. There are many instances when a developer modified the code and then went to the browser to see if the code works, but if he forgot to clean the cache then he may not see any difference despite making changes in the code. During theme development, a developer should always clean the cache to see the modification.

There are instances you will find that even after cleaning the cache the content is not updated at this time you should flush the cache.

Helper Classes

Helper classes contain specific and static methods for specific classes, they cannot be used in other classes. Sometimes the helper class contains multiple functions for multiple issues, which is not an ideal approach for object-oriented code. The Code should be written in such a manner that it contains appropriate methods for that class.

Working on layout

When developers work on layout it is best practice to extend layout which contains modifications according to requirements. Rather than duplicate layout and add extensive changes to a file.If developers require more customization in layout at that time, extending layout is not a good option. In that scenario, overriding that layout is a good option.

Working with Observer

Observer Overriding keeps the capability of modifying the Magento application, as they are injected dynamically into the execution flow of the Magento code, issues such as instability of the code can be caused if the observer overriding is not done properly.

For running your observer seamlessly in your Magento application, the following operation can be performed:

1)The complex computations should be avoided in the code, as more complex computations will slow down the observer, which will result in slow apppcation.

2)The logic contained in the observer should be useful and unnecessary logic should be avoided.

3) 3) The location of the observer places an important role in defining the efficiency of the observer, e.g., if an observer is needed for the frontend it should be declared in /etc/frontend/events.xml file rather than global /etc/events.xml file.

4)Invocation order in the observer should be avoided because due to this one observer may depend on another, which can cause delays in the overall function.

We hope the above blog helps you to clearly understand Magento 2 Coding Standards. In case of any kind of problem with the above code implementation, you can contact us or let us know in the comment section.

Thank You.

Leave a Reply

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