Os Padrões PSR (PHP Standards Recommendations) são um conjunto de especificações criadas pelo PHP-FIG (PHP Framework Interop Group), um grupo colaborativo formado por representantes de diversos projetos PHP populares, como Composer, Laravel, Symfony, Zend Framework, entre outros. O objetivo principal é promover a interoperabilidade entre componentes e bibliotecas PHP, estabelecendo convenções comuns que facilitam a colaboração e a reutilização de código.

Nesta aula, vamos explorar os principais padrões PSR que você precisa conhecer como desenvolvedor PHP moderno: os padrões de estilo de codificação (PSR-1 e PSR-12), o padrão de autoload (PSR-4) e os padrões relacionados a HTTP (PSR-7 e PSR-15). Esses padrões são amplamente adotados no ecossistema PHP e compreendê-los é essencial para escrever código profissional, integrar bibliotecas e contribuir com projetos de código aberto.

O que são

Os Padrões PSR são recomendações (não obrigações) que definem boas práticas para o desenvolvimento em PHP. Eles surgiram da necessidade de unificar comportamentos que eram implementados de maneiras diferentes em cada framework ou biblioteca. Por exemplo, o autoload de classes era feito de formas distintas, o que dificultava a integração entre componentes de diferentes origens.

O PHP-FIG publica esses padrões após um processo de discussão e votação entre seus membros. Cada PSR é identificado por um número e pode ser classificado como:

  • Aceito (Accepted): é um padrão oficial aprovado.
  • Draft: está em discussão.
  • Deprecated: foi substituído ou não é mais recomendado.

Os padrões mais utilizados no dia a dia são: PSR-1 (Basic Coding Standard), PSR-12 (Extended Coding Style), PSR-4 (Autoloading Standard) e PSR-7 (HTTP Message Interface), entre outros. Eles ajudam a garantir que o código seja legível, consistente e interoperável.

PSR-1/PSR-12 (estilo)

O PSR-1 define um conjunto mínimo de regras para a estruturação do código PHP. Ele cobre aspectos como: uso de tags PHP (somente <?php e <?=), codificação em UTF-8 sem BOM, definição de classes, propriedades e métodos, além de convenções de nomenclatura. Por exemplo, classes devem ser nomeadas em StudlyCaps (ex.: MinhaClasse), métodos em camelCase (ex.: meuMetodo), e constantes em MAIÚSCULAS_COM_UNDERSCORE (ex.: MINHA_CONSTANTE).

Já o PSR-12 é uma extensão do PSR-1 e define um estilo de codificação mais detalhado e moderno, baseado no PSR-2, mas atualizado para PHP 7.1+. Ele especifica regras de indentação (4 espaços), chaves em nova linha para classes e métodos, espaçamento em torno de operadores, e a obrigatoriedade de declaração de tipos estritos (declare(strict_types=1);) em arquivos. O PSR-12 também recomenda o uso de use para importar classes e a organização de declarações use em ordem alfabética.

Exemplo de código seguindo PSR-12:

<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Models\User;
use RuntimeException;

class UserController
{
    public function show(int $id): User
    {
        $user = User::find($id);

        if ($user === null) {
            throw new RuntimeException('Usuário não encontrado.');
        }

        return $user;
    }
}

Perceba a indentação consistente, espaçamento adequado, uso de tipos e a organização das declarações use. Essas regras facilitam a leitura e a colaboração em equipe.

PSR-4 (autoload)

O PSR-4 define como as classes devem ser estruturadas em diretórios e como o autoloader deve encontrá-las. Ele é uma evolução do PSR-0, que era mais rígido. O PSR-4 permite mapear um namespace (prefixo) para um diretório base, e a partir daí, cada classe é carregada com base no seu nome totalmente qualificado.

Por exemplo, se você tem o namespace App\ mapeado para o diretório src/, então a classe App\Models\User será encontrada em src/Models/User.php. Isso simplifica a organização do código e elimina a necessidade de incluir manualmente cada arquivo.

O autoloader mais comum é o do Composer. No arquivo composer.json, você define o mapeamento:

{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

Após rodar composer dump-autoload, o Composer gera um autoloader que segue o PSR-4. No seu código, você pode simplesmente usar require 'vendor/autoload.php'; e instanciar classes sem se preocupar com includes.

Exemplo de uso:

<?php

require 'vendor/autoload.php';

use App\Models\User;

$user = new User();

O PSR-4 é um dos padrões mais importantes para o ecossistema PHP, pois permite que bibliotecas sejam instaladas via Composer e funcionem perfeitamente em qualquer projeto que siga o mesmo padrão.

PSR-7/PSR-15 (HTTP, visão geral)

O PSR-7 define interfaces para mensagens HTTP, como requisições (Request) e respostas (Response). Ele padroniza como essas mensagens devem ser representadas em PHP, permitindo que diferentes bibliotecas e frameworks trabalhem juntos. Por exemplo, um middleware pode receber uma Request e retornar uma Response, independentemente da implementação específica.

As principais interfaces do PSR-7 são: Psr\Http\Message\ServerRequestInterface, Psr\Http\Message\ResponseInterface, Psr\Http\Message\StreamInterface, entre outras. Elas definem métodos como getMethod(), getUri(), getBody(), etc.

Já o PSR-15 define interfaces para middlewares e request handlers. Um middleware é um componente que processa uma requisição e pode modificar a resposta ou delegar o processamento ao próximo middleware. O PSR-15 padroniza essa cadeia de responsabilidade, tornando os middlewares intercambiáveis entre diferentes frameworks.

Exemplo de um middleware simples:

<?php

use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class AuthMiddleware implements MiddlewareInterface
{
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        // Verifica se o usuário está autenticado
        if (!isset($_SESSION['user'])) {
            // Redireciona para login (criando uma resposta)
            $response = new \GuzzleHttp\Psr7\Response(302, ['Location' => '/login']);
            return $response;
        }

        // Passa a requisição para o próximo manipulador
        return $handler->handle($request);
    }
}

Esses padrões são fundamentais para o desenvolvimento de aplicações web modernas, pois permitem a criação de componentes reutilizáveis e independentes do framework.

Boas práticas e observações finais

Ao adotar os padrões PSR, você garante que seu código seja mais consistente, legível e interoperável. É importante que sua equipe escolha um conjunto de padrões e os siga rigorosamente. Utilize ferramentas como PHP_CodeSniffer ou PHP-CS-Fixer para automatizar a verificação e correção do estilo de código.

Lembre-se de que os padrões PSR são recomendações, mas a comunidade PHP as adota amplamente. Portanto, seguir esses padrões é uma forma de se alinhar às melhores práticas do ecossistema.

Referências

Exercícios

  1. Explique a importância dos padrões PSR para a interoperabilidade no ecossistema PHP. Dê um exemplo de como a falta de padrões poderia afetar a integração entre bibliotecas.
  2. ✓ Resposta: Os padrões PSR definem convenções comuns para nomes de classes, autoload, estrutura de código e interfaces HTTP. Sem eles, cada biblioteca poderia adotar seu próprio estilo, tornando difícil integrar componentes de diferentes origens. Por exemplo, se uma biblioteca usa um autoloader personalizado e outra usa o PSR-0, o desenvolvedor teria que configurar múltiplos autoloaders manualmente, aumentando a complexidade e o risco de erros.
  3. Escreva um trecho de código PHP que siga o PSR-12, declarando uma classe chamada Produto no namespace App\Models, com uma propriedade privada $nome e um método público getNome() que retorna o nome. Inclua a declaração de tipos estritos.
  4. ✓ Resposta:
    <?php
    
    declare(strict_types=1);
    
    namespace App\Models;
    
    class Produto
    {
        private string $nome;
    
        public function __construct(string $nome)
        {
            $this->nome = $nome;
        }
    
        public function getNome(): string
        {
            return $this->nome;
        }
    }
    
  5. Considere o seguinte mapeamento PSR-4: "App\\": "src/". Onde a classe App\Services\PedidoService deve estar localizada? Explique o caminho completo.
  6. ✓ Resposta: A classe deve estar em src/Services/PedidoService.php. O PSR-4 mapeia o namespace App\ para o diretório src/, então o restante do namespace (Services\) corresponde ao subdiretório Services/ e o nome da classe (PedidoService) corresponde ao arquivo PedidoService.php.
  7. Descreva as principais diferenças entre PSR-7 e PSR-15. Como eles se complementam?
  8. ✓ Resposta: PSR-7 define as interfaces para mensagens HTTP (Request e Response), enquanto PSR-15 define interfaces para middlewares e request handlers. Eles se complementam porque os middlewares (PSR-15) recebem um objeto Request (PSR-7) e retornam uma Response (PSR-7). Juntos, eles permitem construir pipelines de processamento HTTP de forma padronizada e reutilizável.
  9. Crie um middleware PSR-15 que adiciona um header X-Content-Type-Options: nosniff à resposta. Use as interfaces do PSR-7 e PSR-15.
  10. ✓ Resposta:
    <?php
    
    use Psr\Http\Message\ServerRequestInterface;
    use Psr\Http\Message\ResponseInterface;
    use Psr\Http\Server\MiddlewareInterface;
    use Psr\Http\Server\RequestHandlerInterface;
    
    class SecurityHeadersMiddleware implements MiddlewareInterface
    {
        public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
        {
            $response = $handler->handle($request);
            return $response->withHeader('X-Content-Type-Options', 'nosniff');
        }
    }