Skip to content
intermediate Phase 7 · PHP Standards & Tools

PSR-12 Extended Coding Style Guide

Master the PSR-12 coding style guide including indentation, namespace order, class/method spacing, visibility, and Magento code style.

30m
0 problems
Topic Progress 0%

PSR-12 Core Rules

Indentation and Lines

<?php
// MUST use 4 spaces for indentation (no tabs)
class Product
{
    public function getPrice(): float   // 4 spaces
    {                                  // Opening brace on next line
        return $this->price;           // 8 spaces (4 + 4)
    }
}

// There MUST NOT be a hard limit on line length
// The soft limit SHOULD be 120 characters
// Lines SHOULD NOT be longer than 80 characters

// There MUST be one blank line after namespace declaration
namespace Vendor\Module\Model;

// There MUST be one blank line after the use block
use Magento\Framework\Model\AbstractModel;
use Magento\Catalog\Api\ProductRepositoryInterface;

Namespace and Use Statements

<?php
// Namespace declaration
namespace Vendor\Module\Model;

// One blank line after namespace

// One use keyword per declaration
use Magento\Framework\Model\AbstractModel;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Psr\Log\LoggerInterface;

// One blank line after the use block

class Product extends AbstractModel
{
    // ...
}

Class Spacing

<?php
namespace Vendor\Module\Model;

use Magento\Framework\Model\AbstractModel;

class Product extends AbstractModel
{
    // ONE blank line after class opening brace

    public string $name;
    public float $price;

    // ONE blank line between properties and methods

    public function __construct(
        string $name,
        float $price
    ) {
        $this->name = $name;
        $this->price = $price;
    }

    // ONE blank line between methods

    public function getName(): string
    {
        return $this->name;
    }

    public function getPrice(): float
    {
        return $this->price;
    }
}

Method Spacing

<?php
// Method opening brace on NEXT line
class Product
{
    public function getPrice(): float
    {                          // Brace on its own line
        return $this->price;   // Body indented 4 spaces
    }                          // Closing brace

    // No blank line before closing brace (for single-method classes)
}

// Method arguments with defaults go at end
public function create(
    string $name,
    float $price,
    string $sku = '',           // Default at end
    bool $active = true         // Default at end
): Product {
    // ...
}

Visibility

<?php
class Product
{
    // Visibility MUST be declared on ALL properties
    public string $name;         // public
    protected float $price;      // protected
    private string $sku;         // private

    // Visibility MUST be declared on ALL methods
    public function getName(): string {}
    protected function calculateDiscount(): float {}
    private function validateData(): bool {}

    // abstract and final MUST precede visibility
    abstract public function getType(): string;
    final public function getId(): int {}

    // static MUST follow visibility
    public static function getCount(): int {}
}

Key Takeaway

PSR-12 requires 4 spaces indentation, visibility on all members, methods on next line, one blank line between methods, and proper namespace/use statement formatting.

Control Structures and PHP 7+ Features

Control Structures

<?php
// Opening brace on SAME line for control structures
if ($condition) {
    // ...
} elseif ($otherCondition) {
    // ...
} else {
    // ...
}

// switch statement
switch ($value) {
    case 1:
        // ...
        break;
    case 2:
        // ...
        break;
    default:
        // ...
        break;
}

// while, for, foreach
while ($condition) {
    // ...
}

for ($i = 0; $i < 10; $i++) {
    // ...
}

foreach ($items as $key => $value) {
    // ...
}

// try-catch-finally
try {
    // ...
} catch (\Exception $e) {
    // ...
} finally {
    // ...
}

Ternary and Null Coalescing

<?php
// Ternary operator
$value = $condition ? $trueValue : $falseValue;

// Multiline ternary (each part on its own line)
$value = $condition
    ? $trueValue
    : $falseValue;

// Null coalescing
$value = $variable ?? 'default';

// Chained
$value = $a ?? $b ?? $c ?? 'default';

PHP 7+ Features

<?php
// Return type declarations
function getPrice(): float
{
    return $this->price;
}

// Nullable return type
function findProduct(int $id): ?Product
{
    return $this->repository->getById($id);
}

// Scalar type hints
function formatPrice(float $price, string $currency = 'USD'): string
{
    return number_format($price, 2) . ' ' . $currency;
}

// Short array syntax (preferred)
$array = [1, 2, 3];
$assoc = ['key' => 'value'];

// Long array syntax (avoid)
$array = array(1, 2, 3);

PHP 8 Features

<?php
// Constructor promotion
class Product
{
    public function __construct(
        public readonly string $name,
        public readonly float $price,
    ) {}
}

// Named arguments
createUser(
    email: 'user@example.com',
    name: 'John',
    role: 'admin'
);

// Match expression
$result = match($status) {
    200 => 'OK',
    404 => 'Not Found',
    default => 'Unknown',
};

// Union types
function formatId(int|string $id): string
{
    return (string)$id;
}

Key Takeaway

Control structures use opening braces on the same line. Methods use braces on the next line. PHP 7+ features (return types, type hints) are standard. PHP 8 features (match, named args) follow the same style rules.

Quiz

1. How many spaces does PSR-12 require for indentation?

Question 1 options

2. Where does a method's opening brace go in PSR-12?

Question 2 options

3. What must precede the visibility keyword on abstract and final methods?

Question 3 options

4. How many use keywords per declaration does PSR-12 require?

Question 4 options

5. Where does a control structure's opening brace go?

Question 5 options

Flashcards

Question

How many spaces for PSR-12 indentation?

Answer

4 spaces. No tabs allowed.

Question

Where do method braces go?

Answer

Opening brace on NEXT line after the method declaration. Body indented 4 more spaces.

Question

Where do control structure braces go?

Answer

Opening brace on SAME line as the keyword. if (...) { on one line.

Question

What precedes visibility on abstract/final methods?

Answer

abstract or final comes BEFORE visibility. abstract public function, final public function.

Question

What follows visibility for static methods?

Answer

static comes AFTER visibility. public static function, protected static function.

Question

How many use keywords per line?

Answer

One use keyword per declaration, each on its own line.

Question

How many blank lines after namespace?

Answer

One blank line after the namespace declaration, and one blank line after the use block.

Question

Where do default parameter values go?

Answer

At the end of the parameter list. Required parameters first, then parameters with defaults.

Revision Notes

Key Takeaways

  • 1. 4 spaces indentation, no tabs
  • 2. Method braces on next line, control structure braces on same line
  • 3. Visibility required on ALL properties and methods
  • 4. abstract/final before visibility, static after
  • 5. One use keyword per declaration
  • 6. One blank line after namespace and after use block
  • 7. Default parameters at end of parameter list

Interview Tips

  • Explain the difference between method and control structure brace placement
  • Know where abstract/final/static go relative to visibility
  • Describe proper namespace and use statement formatting
  • Apply PSR-12 rules to format a class correctly
  • Know the difference between PSR-1 and PSR-12

Cheat Sheet

PSR-12 Cheat Sheet

Indentation: 4 spaces, no tabs

Braces:

  • Methods: next line
  • Control structures: same line
  • Classes: next line

Visibility:

  • Required on ALL properties and methods
  • abstract/final BEFORE visibility
  • static AFTER visibility

Namespace/Use:

  • One blank line after namespace
  • One use per declaration
  • One blank line after use block

Methods:

  • One blank line between methods
  • Default params at end
  • Return type on same line

Properties:

  • Type declarations required
  • One blank line between property groups