Understanding the PSR-12 Standard
PHP Standards Recommendations (PSRs) are guidelines designed to promote consistency across PHP projects. Among these, PSR-12 (Extended Coding Style Guide) is the modern standard for formatting PHP code. It builds on PSR-2 and incorporates updates for newer PHP features (e.g., type declarations, anonymous classes, and closures). Adhering to PSR-12 ensures code readability, simplifies collaboration, and reduces cognitive friction when working across projects.
Understanding the PSR-12 Standard
PSR-12 defines strict rules for code structure, spacing, indentation, and line length. Here are the key requirements:
1. File Structure
- Files MUST start with
<?php
(without a closing?>
tag). - Strict type declaration (
declare(strict_types=1)
) MUST follow the opening tag. - Namespace declarations MUST come after the
declare
statement. - Use statements MUST be grouped by root namespace and separated by a blank line.
2. Class and Method Definitions
- Classes MUST have braces on separate lines.
- The
extends
andimplements
keywords MUST be on the same line as the class name. - Method arguments spanning multiple lines MUST be indented once (4 spaces).
- Visibility modifiers (e.g.,
public
,private
) MUST be declared for all properties and methods.
3. Control Structures
- Control structure keywords (e.g.,
if
,for
,foreach
) MUST have one space after them. - Opening braces MUST be on the same line as the declaration, and closing braces MUST be on a new line.
- Multi-line conditions MUST split lines after logical operators, with subsequent lines indented once.
4. Spacing and Line Length
- Lines SHOULD NOT exceed 120 characters.
- Operators (e.g.,
=
,.
,+
) MUST be surrounded by spaces. - Type declarations (e.g.,
string $param
) MUST NOT have spaces between the type and variable.
5. Anonymous Functions and Closures
- A space MUST follow the
function
keyword. - The
use
keyword and opening brace MUST be on the same line.
Real-World Examples
Example 1: Class Definition
<?php
declare(strict_types=1);
namespace Vendor\Package;
use Vendor\Package\FirstNamespace\ClassA;
use Vendor\Package\FirstNamespace\ClassB;
use Vendor\Package\SecondNamespace\ClassC;
class SampleClass extends ParentClass implements InterfaceA, InterfaceB
{
private const MODE_DEBUG = 'debug';
private string $property;
public function __construct(
string $param1,
int $param2,
array $param3 = []
) {
$this->property = $param1;
}
public function doSomething(
int $input,
string $text
): string {
if ($input > 0
&& $text !== ''
) {
return $this->property . $text;
}
return '';
}
}
Example 2: Control Structures
// `if` statement with multi-line conditions
if ($condition1
&& $condition2
&& $condition3
) {
// Code
}
// Anonymous function
$closure = function () use ($var1, $var2): string {
return $var1 . $var2;
};
Best Practices
1. Automate Formatting
Use tools like PHP-CS-Fixer or PHP_CodeSniffer to enforce PSR-12:
php-cs-fixer fix src --rules=@PSR12
2. IDE Configuration
Configure your editor (e.g., PhpStorm, VSCode) to:
- Use 4 spaces for indentation.
- Trim trailing whitespace.
- Set a line length limit of 120 characters.
3. Code Reviews
Include style checks in pull request reviews to catch deviations early.
Common Pitfalls and How to Avoid Them
- Mixing Spaces and Tabs
Ensure your editor converts tabs to 4 spaces. - Incorrect Use Statement Grouping
Groupuse
statements by namespace and separate groups with a blank line:
use Vendor\Package\First\{ClassA, ClassB};
use Vendor\Package\Second\ClassC;
use OtherVendor\Package\ClassD;
- Ignoring Line Length Limits
Break long lines using method chaining or splitting arguments:
$result = $this->someService->executeLongMethodName(
$argument1,
$argument2,
$argument3
);
Monitoring and Enforcing PSR-12
1. Static Analysis Tools
- PHP_CodeSniffer:
Install and run with the PSR-12 ruleset:
composer require squizlabs/php_codesniffer
phpcs --standard=PSR12 src/
- PHP-CS-Fixer:
Automatically fix violations:
composer require friendsofphp/php-cs-fixer
php-cs-fixer fix --rules=@PSR12
2. Continuous Integration (CI)
Add a CI step (e.g., GitHub Actions) to block non-compliant code:
# .github/workflows/phpcs.yml
name: PHP_CodeSniffer
on: [push]
jobs:
phpcs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run PHP_CodeSniffer
run: |
composer install
vendor/bin/phpcs --standard=PSR12 src/
Example for on GitLab here:
3. Pre-commit Hooks
Use tools like pre-commit
to run checks before commits:
composer require --dev phpro/grumphp
Conclusion
PSR-12 is a cornerstone of maintainable PHP code. By adopting it, teams reduce style debates, improve code quality, and streamline collaboration. Combine automated tools, CI/CD pipelines, and developer education to enforce the standard effectively. Remember: consistency is key — whether working on legacy projects or new greenfield applications.