PHP 8: Modern PHP Development · Composer, Autoloading and PSR Standards

PSR Standards You Should Know

PSR-3 logging, PSR-7/15/17/18 HTTP, PSR-11 containers, PSR-20 clocks and PER coding style.

The PHP Framework Interop Group (PHP-FIG) publishes standards that let libraries interoperate. Key ones: PSR-1/PSR-12 and PER Coding Style (formatting), PSR-3 (LoggerInterface), PSR-4 (autoloading), PSR-6/16 (caching), PSR-7 (HTTP messages), PSR-11 (containers), PSR-14 (event dispatcher), PSR-15 (HTTP middleware), PSR-17 (HTTP factories), PSR-18 (HTTP client) and PSR-20 (clock). Type-hint against these interfaces to stay framework-agnostic.

<?php
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Log\LoggerInterface;

final class TimingMiddleware implements MiddlewareInterface     // PSR-15
{
    public function __construct(private LoggerInterface $logger) {}   // PSR-3

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $start = hrtime(true);
        $response = $handler->handle($request);
        $this->logger->info('request', [
            'path' => $request->getUri()->getPath(),
            'status' => $response->getStatusCode(),
            'ms' => (hrtime(true) - $start) / 1e6,
        ]);
        return $response->withHeader('Server-Timing', 'app');      // PSR-7 is immutable
    }
}

Common pitfalls

  • Mutating PSR-7 messages — with*() returns a new instance; ignoring the return value loses the change.
  • Coupling libraries to a specific framework's logger instead of PSR-3.
  • Using the container as a service locator everywhere (PSR-11 is for composition roots).

Key points

  • PSRs make libraries interoperable
  • PSR-7 messages are immutable
  • Type-hint PSR interfaces in reusable code

Further reading: PHP-FIG PSR index

Practice questions

Why does $response->withHeader('X', '1'); alone not add the header?

Answer

PSR-7 messages are immutable; withHeader() returns a new response. You must use the returned value: $response = $response->withHeader(...).

What problem does PSR-3 solve?

Answer

It defines a common LoggerInterface, so libraries can log without depending on a specific logging implementation; the application chooses Monolog or another PSR-3 logger.

Open in the app to mark lessons complete, take notes and track your progress.