Most PSRs are small interfaces in psr/* packages: code that type-hints Psr\Log\LoggerInterface accepts Monolog 21,402 or any other logger. Statuses are from php-fig.org:
| PSR | Subject | Status | You meet it in |
|---|---|---|---|
| 1 | Basic coding standard | Accepted | Naming (Coding Standards) |
| 3 | Logger interface | Accepted | Monolog (Monolog) |
| 4 | Autoloading | Accepted | Composer 5,243 (PSR-4 and Directory Layout) |
| 7 | HTTP messages | Accepted | Guzzle 23,452 , Slim 32,516 |
| 11 | Container interface | Accepted | DI containers (Dependency Injection) |
| 12 | Extended coding style | Accepted; PER-CS replaces it | Formatters |
| 15 | HTTP handlers, middleware | Accepted | Mezzio, Slim |
| 17 | HTTP factories | Accepted | Building PSR-7 objects |
| 18 | HTTP client | Accepted | Guzzle 7+ |
| 20 | Clock | Accepted | Testable time |
PSR-0 and PSR-2 are deprecated; PSR-5 and PSR-19 (PHPDoc) are drafts. PSR-20 (composer require psr/clock) is the easiest win: code that asks a clock for the time is testable.
<?php
require __DIR__ . '/vendor/autoload.php';
final readonly class FrozenClock implements Psr\Clock\ClockInterface { // PSR-20
public function __construct(private DateTimeImmutable $at) {}
public function now(): DateTimeImmutable { return $this->at; }
}
function banner(Psr\Clock\ClockInterface $clock): string {
return $clock->now() < new DateTimeImmutable('2026-12-01') ? 'Autumn sale' : '';
}
var_dump(banner(new FrozenClock(new DateTimeImmutable('2026-11-30 23:59'))),
banner(new FrozenClock(new DateTimeImmutable('2026-12-01 00:00'))));Output
string(11) "Autumn sale" string(0) ""
In production, pass a real-time clock such as symfony/clock's NativeClock.