Skip to content
intermediate Phase 12 · Testing & Quality

PHP CodeSniffer & Magento Coding Standards

PHP CodeSniffer, sniff rules, custom standards, and Magento coding standards (Magento2 coding standard)

45m
0 problems
Topic Progress 0%

PHP CodeSniffer Basics

What is PHP CodeSniffer?

PHP CodeSniffer (PHPCS) detects violations of coding standards. It's a static analysis tool focused on code style.

Installation

composer require --dev squizlabs/php_codesniffer
composer require --dev magento/magento-coding-standard

Basic Usage

# Check a file
vendor/bin/phpcs app/code/Vendor/Module/Model/Product.php

# Check a directory
vendor/bin/phpcs app/code/Vendor/Module/

# Use Magento standard
vendor/bin/phpcs --standard=Magento2 app/code/Vendor/Module/

# Auto-fix issues
vendor/bin/phpcbf --standard=Magento2 app/code/Vendor/Module/

# Show report in different format
vendor/bin/phpcs --report=csv app/code/Vendor/Module/

php.xml Configuration

<!-- phpcs.xml -->
<ruleset name="Magento2 Custom">
    <description>Custom Magento 2 coding standard</description>

    <arg name="extensions" value="php"/>
    <arg value="sp"/> <!-- Show progress -->

    <!-- Use Magento2 standard as base -->
    <rule ref="Magento2"/>

    <!-- Paths to check -->
    <file>app/code/Vendor/Module</file>

    <!-- Exclude files -->
    <exclude-pattern>*/Test/*</exclude-pattern>
    <exclude-pattern>*/generated/*</exclude-pattern>
    <exclude-pattern>*/_files/*</exclude-pattern>

    <!-- Config -->
    <config name="minimum_supported_php_version" value="8.1"/>
    <config name="testVersion" value="8.1-"/>
</ruleset>

Running

# Use phpcs.xml config automatically
vendor/bin/phpcs

# Or specify config
vendor/bin/phpcs --standard=phpcs.xml

Magento 2 Coding Standard

Key Magento 2 Coding Rules

Naming Conventions

// Classes: PascalCase
namespace Vendor\Module\Model;

class ProductExporter { /* ... */ } // Correct
class product_exporter { /* ... */ } // Wrong

// Methods: camelCase
public function getProductPrice(): float { /* ... */ } // Correct
public function get_product_price(): float { /* ... */ } // Wrong

// Variables: camelCase
$productName = 'Test'; // Correct
$product_name = 'Test'; // Wrong (unless snake_case for DB columns)

// Constants: UPPER_SNAKE_CASE
public const STATUS_ACTIVE = 1; // Correct
public const statusActive = 1; // Wrong

Indentation and Spacing

// 4 spaces indentation (no tabs)
class Product
{
    public function getName(): string // Space after method name
    {
        return $this->name; // 4 spaces, not tabs
    }
}

// Space after comma in arrays
$array = ['key1' => 'value1', 'key2' => 'value2'];

// No space before semicolon
$value = 'test'; // Correct
$value = 'test' ; // Wrong

PHPDoc Requirements

/**
 * Product export service.
 *
 * @api
 */
class ProductExporter
{
    /**
     * Export product data to CSV format.
     *
     * @param ProductInterface $product
     * @return string CSV formatted data
     * @throws \InvalidArgumentException if product is null
     */
    public function export(ProductInterface $product): string
    {
        // ...
    }
}

Magento-Specific Rules

// Use __() for translatable strings
throw new \Magento\Framework\Exception\LocalizedException(
    __('Product not found')
); // Correct
throw new \Magento\Framework\Exception\LocalizedException(
    new \Magento\Framework\Phrase('Product not found')
); // Also correct, but __() is preferred

// Use interfaces for type hints
public function save(\Magento\Catalog\Api\Data\ProductInterface $product) // Correct
public function save(\Magento\Catalog\Model\Product $product) // Wrong

Custom Sniffs and PHP-CS-Fixer

Custom Sniff Rule

namespace Vendor\Module\PHP_CodeSniffer\Sniffs\Commenting;

use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;

class ForbiddenTODOCommentSniff implements Sniff
{
    public function register(): array
    {
        return [T_COMMENT];
    }

    public function process(File $phpcsFile, $stackPtr): void
    {
        $comment = $phpcsFile->getTokens()[$stackPtr];

        if (str_contains($comment['content'], 'TODO') ||
            str_contains($comment['content'], 'FIXME')) {
            $phpcsFile->addWarning(
                'TODO/FIXME comments are not allowed in production code',
                $stackPtr,
                'ForbiddenTodo'
            );
        }
    }
}

Register in ruleset:

<ruleset name="Magento2 Custom">
    <rule ref="Magento2"/>
    <rule name="Vendor\Module\PHP_CodeSniffer\Sniffs\Commenting\ForbiddenTODOCommentSniff"/>
</ruleset>

PHP-CS-Fixer (Alternative)

# Install
composer require --dev friendsofphp/php-cs-fixer

# Run
vendor/bin/php-cs-fixer fix app/code/Vendor/Module/

# Dry run (show changes without applying)
vendor/bin/php-cs-fixer fix --dry-run --diff app/code/Vendor/Module/
// .php-cs-fixer.dist.php
return (new PhpCsFixer\Config())
    ->setRules([
        '@PER-CS2.0' => true,
        'array_syntax' => ['syntax' => 'short'],
        'no_unused_imports' => true,
        'ordered_imports' => ['sort_algorithm' => 'alpha'],
        'single_quote' => true,
        'trailing_comma_in_multiline' => true,
    ])
    ->setFinder(
        PhpCsFixer\Finder::create()
            ->in(__DIR__ . '/app/code/Vendor/Module')
    );

CI Integration

# .github/workflows/coding-standard.yml
name: Coding Standard
on: [push, pull_request]

jobs:
  phpcs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.1'
      - run: composer install
      - run: vendor/bin/phpcs --standard=phpcs.xml --report=checkstyle > phpcs.xml

  php-cs-fixer:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.1'
      - run: composer install
      - run: vendor/bin/php-cs-fixer fix --dry-run --diff

Quiz

1. What is the Magento 2 coding standard for class names?

Question 1 options

2. How do you auto-fix PHPCS violations?

Question 2 options

3. PHPCS is primarily for detecting:

Question 3 options

Flashcards

Question

What does PHPCS detect?

Answer

Coding standard violations (style, naming, formatting)

Question

Magento 2 class naming convention?

Answer

PascalCase (ProductExporter, OrderRepository)

Question

How to auto-fix PHPCS violations?

Answer

vendor/bin/phpcbf --standard=Magento2

Question

Magento coding standard package?

Answer

magento/magento-coding-standard

Revision Notes

Key Takeaways

  • 1. PHPCS detects coding standard violations (style, naming, formatting)
  • 2. Magento 2 standard: PascalCase classes, camelCase methods, 4-space indentation
  • 3. phpcbf auto-fixes violations; phpstan finds type errors
  • 4. PHP-CS-Fixer is an alternative with more configurable rules
  • 5. Integrate both into CI pipeline for consistent code style

Interview Tips

  • Know Magento naming conventions: PascalCase classes, camelCase methods
  • Explain the difference between PHPCS (style) and PHPStan (types)
  • Discuss how to adopt coding standards gradually in existing codebases

Cheat Sheet

PHPCS:  vendor/bin/phpcs --standard=Magento2 src/
PHPCBF: vendor/bin/phpcbf --standard=Magento2 src/

Magento2 Standard:
  Classes:      PascalCase
  Methods:      camelCase
  Constants:    UPPER_SNAKE_CASE
  Indentation:  4 spaces (no tabs)
  Strings:      Use __() for translatable strings

Config: phpcs.xml
  <rule ref="Magento2"/>
  <file>app/code/Vendor/Module</file>
  <exclude-pattern>*/Test/*</exclude-pattern>