SkillByAIOpen interactive version →

Lesson 19 / 25

PHP-FIG Standards: PSRs and Coding Style

Use the key PSR interfaces and coding style standards.

Shared interfaces across the ecosystem

The PHP Framework Interop Group (PHP-FIG) publishes PSRs (PHP Standards Recommendations) so libraries and frameworks can work together. Key ones: PSR-4 (autoloading), PSR-3 (LoggerInterface), PSR-7 (HTTP message interfaces: immutable request and response objects), PSR-15 (HTTP server request handlers and middleware), PSR-17 (HTTP factories), PSR-18 (HTTP client), PSR-11 (container interface), PSR-6 and PSR-16 (caching) and PSR-14 (event dispatcher). Coding style is defined by the PER Coding Style (the evolving successor to PSR-12): four-space indentation, braces placement, declare(strict_types=1) placement, and so on. Enforce it automatically with PHP-CS-Fixer or PHP_CodeSniffer, so reviews focus on design rather than spaces. Middleware following PSR-15 wraps a handler: each middleware can inspect or change the request, call the next handler, and modify the response, which is how authentication, logging, CORS and rate limiting are layered in frameworks such as Slim and Mezzio.

Middleware layers

A request passes inward through middleware to the handler, and the response travels back out.

Figure 7.1 — PSR-15 middleware wrapping a request handler.

A PSR-15 middleware

Adds a request ID and measures timing for every request.

<?php
declare(strict_types=1);

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 RequestTiming implements MiddlewareInterface
{
    public function __construct(private readonly LoggerInterface $logger) {}

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $id = $request->getHeaderLine('X-Request-Id') ?: bin2hex(random_bytes(8));
        $start = hrtime(true);

        $response = $handler->handle($request->withAttribute('request_id', $id));   // PSR-7 objects are immutable

        $ms = (hrtime(true) - $start) / 1e6;
        $this->logger->info('request', ['id' => $id, 'path' => $request->getUri()->getPath(), 'ms' => round($ms, 1)]);
        return $response->withHeader('X-Request-Id', $id);
    }
}

// vendor/bin/php-cs-fixer fix src --rules=@PER-CS   (automatic code style)

PSR-7 objects are immutable

$request->withAttribute(...) returns a new request; it does not change the original. Forgetting to use the returned object is a common bug when writing middleware.

Quick check: What does PSR-15 standardise?

  • HTTP server request handlers and middleware
  • Autoloading
  • Logging
  • Coding style
Answer

HTTP server request handlers and middleware — PSR-15 defines MiddlewareInterface and RequestHandlerInterface.