PSR-12 i PHP-CS-Fixer
🎯 Po tej lekcji zainstalujesz PHP-CS-Fixer jako zależność deweloperską, uruchomisz formatowanie projektu i skonfigurujesz reguły PSR-12.
Gdy w projekcie pracuje kilka osób, każda może formatować kod inaczej — jedne używają tabulatorów, inne spacji; jedne stawiają klamrę otwierającą w tej samej linii co deklarację funkcji, inne w następnej. PSR-12 to standard stylu kodu PHP, który eliminuje te spory. PHP-CS-Fixer automatycznie stosuje ten standard w Twoich plikach.
Czym jest PSR-12?
PSR-12 (PHP Standards Recommendation 12) to zestaw reguł formatowania kodu wydany przez PHP-FIG (Framework Interoperability Group). Określa m.in.:
- Wcięcia: 4 spacje (nie tabulatory)
- Klamra otwierająca klas i metod: w nowej linii
- Klamra otwierająca pętli i warunków: w tej samej linii
- Spacje wokół operatorów:
$a + $b, nie$a+$b - Brak zbędnych spacji na końcu linii
- Jedna pusta linia po
declare(strict_types=1); - Kody pliku: UTF-8, zakończenia linii Unix (
\n)
PSR-12 jest oparty na PSR-1 i PSR-2 (poprzednie wersje) i jest dziś domyślnym standardem większości frameworków PHP.
Instalacja PHP-CS-Fixer jako --dev
PHP-CS-Fixer to narzędzie deweloperskie — nie jest potrzebne na produkcji. Instalujemy je z flagą --dev:
composer require --dev friendsofphp/php-cs-fixer
Composer doda pakiet do sekcji require-dev w composer.json:
{
"require": {
"php": ">=8.1",
"monolog/monolog": "^3.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0"
}
}
Plik wykonywalny znajdziesz w vendor/bin/:
vendor/bin/php-cs-fixer --version
Użycie: fix — formatuj kod
Żeby sformatować cały katalog src/ według PSR-12:
vendor/bin/php-cs-fixer fix src/ --rules=@PSR12
Opcja --diff pokazuje zmiany bez ich stosowania (tryb podglądu):
vendor/bin/php-cs-fixer fix src/ --rules=@PSR12 --diff --dry-run
Przykładowy wynik:
1) src/Services/Email.php (braces, indentation_type, no_extra_blank_lines)
Fixed 1 of 1 files in 0.123 seconds, 14.0 MB memory used
Plik konfiguracyjny .php-cs-fixer.php
Zamiast podawać reguły za każdym razem w terminalu, utwórz plik .php-cs-fixer.php w katalogu głównym projektu:
<?php
declare(strict_types=1);
$finder = PhpCsFixer\Finder::create()
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests');
return (new PhpCsFixer\Config())
->setRules([
'@PSR12' => true,
'array_syntax' => ['syntax' => 'short'], // [] zamiast array()
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'no_unused_imports' => true,
])
->setFinder($finder);
Teraz samo vendor/bin/php-cs-fixer fix odczyta konfigurację automatycznie:
vendor/bin/php-cs-fixer fix
Najważniejsze reguły PSR-12 — przykłady
Wcięcia (4 spacje) i klamry klas
<?php
declare(strict_types=1);
// DOBRZE — klamra otwierająca klasy w nowej linii
class Kalkulator
{
public function dodaj(int $a, int $b): int
{
return $a + $b;
}
}
Klamry w pętlach i warunkach
<?php
declare(strict_types=1);
// DOBRZE — klamra w tej samej linii co if/for/foreach
function filtrujDoroslych(array $osoby): array
{
$wynik = [];
foreach ($osoby as $osoba) {
if ($osoba['wiek'] >= 18) {
$wynik[] = $osoba;
}
}
return $wynik;
}
Import klas (use)
<?php
declare(strict_types=1);
namespace App\Services;
// DOBRZE — use po deklaracji namespace, jedno use na linię, alphabetycznie
use App\Models\Produkt;
use App\Models\Uzytkownik;
use Monolog\Logger;
class ZamowienieService
{
// ...
}
Widoczność właściwości
<?php
declare(strict_types=1);
class Produkt
{
// DOBRZE — najpierw stałe, potem właściwości, potem metody
public const WALUTA = 'PLN';
private string $nazwa;
private float $cena;
public function __construct(string $nazwa, float $cena)
{
$this->nazwa = $nazwa;
$this->cena = $cena;
}
public function getNazwa(): string
{
return $this->nazwa;
}
}
Dodanie skryptu do composer.json
Możesz skrócić wywoływanie PHP-CS-Fixer przez sekcję scripts w composer.json:
{
"scripts": {
"fix": "vendor/bin/php-cs-fixer fix",
"check": "vendor/bin/php-cs-fixer fix --dry-run --diff"
}
}
Potem wystarczy:
composer fix # formatuj kod
composer check # sprawdź bez zmian
composer check, który kończy się błędem, jeśli kod nie spełnia standardu PSR-12. Dzięki temu do repozytorium nie trafia niesformatowany kod.require-dev na produkcji — pomiń narzędzia deweloperskie
Na serwerze produkcyjnym nie instaluj pakietów deweloperskich:
composer install --no-dev
Flaga --no-dev pomija sekcję require-dev. PHP-CS-Fixer, PHPUnit i inne narzędzia deweloperskie nie trafią na produkcję, co zmniejsza rozmiar katalogu vendor/ i powierzchnię ataku.
Podsumowanie modułu
W tym module przeszedłeś przez cały nowoczesny warsztat PHP:
- Composer — zarządzanie zależnościami,
composer.json, Packagist - Autoloading PSR-4 — mapowanie namespace → katalog,
composer dump-autoload - Zewnętrzna biblioteka — Monolog,
vendor/,composer.lock,.gitignore - PSR-12 i PHP-CS-Fixer — spójny styl kodu, automatyczne formatowanie
To podstawy warsztatu, których używasz w każdym profesjonalnym projekcie PHP.
Sprawdź się
Jakiej flagi używasz, żeby zainstalować pakiet tylko dla środowiska deweloperskiego?
Flaga --dev powoduje, że Composer zapisuje pakiet w sekcji require-dev w composer.json. Pakiety z require-dev nie są instalowane na produkcji przy composer install --no-dev. Dzięki temu narzędzia do testowania i formatowania kodu nie trafiają na serwer.
W jakiej sekcji composer.json lądują pakiety zainstalowane przez composer require --dev?
composer require --dev pakiet dopisuje go do sekcji require-dev. Sekcja autoload-dev to osobna sprawa — służy do konfiguracji autoloadera dla klas testowych, a nie do zarządzania zależnościami.
Jaką komendą uruchomisz PHP-CS-Fixer na całym katalogu src/?
Pliki wykonywalne zainstalowanych pakietów Composer umieszcza w vendor/bin/. Dlatego uruchamiasz php-cs-fixer jako vendor/bin/php-cs-fixer. Możesz też dodać ten katalog do PATH, ale odwoływanie się przez vendor/bin/ jest powszechnym standardem.
Ćwiczenie
Zainstaluj PHP-CS-Fixer jako --dev. Napisz celowo 'brzydki' plik src/Brzydki.php (złe wcięcia, brak spacji wokół operatorów, niepotrzebne spacje). Uruchom vendor/bin/php-cs-fixer fix src/Brzydki.php --rules=@PSR12 i sprawdź, co zostało zmienione. Opcjonalnie: dodaj plik .php-cs-fixer.php z konfiguracją i uruchom fix bez podawania reguł ręcznie.
Pokaż rozwiązanie
# Instalacja:
composer require --dev friendsofphp/php-cs-fixer
# src/Brzydki.php (celowo źle sformatowany)
<?php
declare(strict_types=1);
class Brzydki{
public function licz($a,$b){return $a+$b;}
}
# Formatowanie:
vendor/bin/php-cs-fixer fix src/Brzydki.php --rules=@PSR12
# Wynik (po naprawieniu przez fixer):
<?php
declare(strict_types=1);
class Brzydki
{
public function licz($a, $b)
{
return $a + $b;
}
}
# Plik .php-cs-fixer.php:
<?php
declare(strict_types=1);
$finder = PhpCsFixer\Finder::create()->in(__DIR__ . '/src');
return (new PhpCsFixer\Config())
->setRules(['@PSR12' => true])
->setFinder($finder);