PSR Catalog

The PSR Catalog: Interfaces Worth Implementing

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:

Key PSRs and their status (September 2026)
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.

PSR-20: a sale banner checked against a frozen clock (clock.php)PHP
<?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.