Guia Completo de Roteamento HTTP em PHP: Criando um Router Simples Já leu

O que é Roteamento HTTP e Por Que Importa Roteamento HTTP é o mecanismo fundamental que mapeia URLs para ações específicas em sua aplicação. Quando um usuário acessa , o router é responsável por identificar qual código deve ser executado. Em frameworks modernos como Laravel ou Symfony, esse processo é automatizado, mas entender como criar um router do zero é essencial para compreender a arquitetura web e desenvolver soluções customizadas. Um router bem estruturado oferece controle total sobre sua aplicação, melhora a manutenção do código e permite implementar padrões avançados como RESTful APIs com facilidade. Vamos construir um router simples, mas robusto, que você poderá usar em projetos pequenos ou expandir conforme suas necessidades crescerem. Fundamentos: Como um Router Funciona Capturando a URL e o Método HTTP Todo router começa capturando a URL solicitada e o método HTTP utilizado. Em PHP, isso é feito através de variáveis superglobais. O primeiro passo é extrair o caminho da URL e remover parâmetros

O que é Roteamento HTTP e Por Que Importa

Roteamento HTTP é o mecanismo fundamental que mapeia URLs para ações específicas em sua aplicação. Quando um usuário acessa exemplo.com/usuarios/123, o router é responsável por identificar qual código deve ser executado. Em frameworks modernos como Laravel ou Symfony, esse processo é automatizado, mas entender como criar um router do zero é essencial para compreender a arquitetura web e desenvolver soluções customizadas.

Um router bem estruturado oferece controle total sobre sua aplicação, melhora a manutenção do código e permite implementar padrões avançados como RESTful APIs com facilidade. Vamos construir um router simples, mas robusto, que você poderá usar em projetos pequenos ou expandir conforme suas necessidades crescerem.

Fundamentos: Como um Router Funciona

Capturando a URL e o Método HTTP

Todo router começa capturando a URL solicitada e o método HTTP utilizado. Em PHP, isso é feito através de variáveis superglobais. O primeiro passo é extrair o caminho da URL e remover parâmetros de query:

<?php
class Router {
    private $routes = [];

    public function __construct() {
        $this->parseRequest();
    }

    private function parseRequest() {
        $method = $_SERVER['REQUEST_METHOD'];
        $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

        // Remove a barra final para padronizar
        $path = rtrim($path, '/') ?: '/';

        return [$method, $path];
    }
}

Este código extrai o método HTTP (GET, POST, PUT, DELETE) e o caminho limpo. A função parse_url() garante que parâmetros query sejam ignorados, mantendo apenas a estrutura da rota.

Registrando Rotas

Agora precisamos de um sistema para registrar rotas e associá-las a callbacks:

public function get($path, $callback) {
    $this->routes['GET'][$path] = $callback;
}

public function post($path, $callback) {
    $this->routes['POST'][$path] = $callback;
}

public function put($path, $callback) {
    $this->routes['PUT'][$path] = $callback;
}

public function delete($path, $callback) {
    $this->routes['DELETE'][$path] = $callback;
}

Cada método HTTP recebe uma rota (caminho) e uma função (callback) que será executada quando essa rota for acessada. O callback pode ser uma função anônima ou uma string referenciando um controller.

Implementação: Criando um Router Completo

Suportando Rotas Dinâmicas com Parâmetros

Rotas estáticas são úteis, mas a maioria das aplicações precisa de parâmetros dinâmicos. Vamos adicionar suporte a :id e similares:

private function matchRoute($method, $path) {
    // Verifica rota exata primeiro
    if (isset($this->routes[$method][$path])) {
        return [$this->routes[$method][$path], []];
    }

    // Verifica rotas com parâmetros
    if (!isset($this->routes[$method])) {
        return null;
    }

    foreach ($this->routes[$method] as $route => $callback) {
        $pattern = preg_replace('/:[a-zA-Z_][a-zA-Z0-9_]*/', '([^/]+)', $route);
        $pattern = '#^' . $pattern . '$#';

        if (preg_match($pattern, $path, $matches)) {
            array_shift($matches); // Remove a correspondência completa

            // Extrai nomes dos parâmetros
            preg_match_all('/:[a-zA-Z_][a-zA-Z0-9_]*/', $route, $params);
            $params = array_map(fn($p) => substr($p, 1), $params[0]);

            $params = array_combine($params, $matches);
            return [$callback, $params];
        }
    }

    return null;
}

Este método usa regex para transformar rotas como /usuarios/:id em padrões capturáveis. Se encontrar uma correspondência, retorna o callback e um array com os parâmetros extraídos.

Executando o Router

Agora vamos adicionar o método que executa toda a lógica:

public function dispatch() {
    [$method, $path] = $this->parseRequest();

    $result = $this->matchRoute($method, $path);

    if ($result === null) {
        http_response_code(404);
        echo "Rota não encontrada: $method $path";
        return;
    }

    [$callback, $params] = $result;

    // Se for string, assume que é um controller@action
    if (is_string($callback)) {
        [$class, $action] = explode('@', $callback);
        $controller = new $class();
        echo $controller->$action($params);
    } else {
        // Se for closure ou função
        echo call_user_func_array($callback, array_values($params));
    }
}

Exemplo Prático: Usando o Router

Aplicação Completa Funcionando

<?php
// Arquivo: router.php - Contém a classe Router completa

$router = new Router();

// Rotas simples
$router->get('/', function() {
    return "Bem-vindo à página inicial!";
});

// Rotas com parâmetros
$router->get('/usuarios/:id', function($id) {
    return "Visualizando usuário ID: $id";
});

// Rotas POST
$router->post('/usuarios', function() {
    return "Novo usuário criado!";
});

// Usando controllers (string)
$router->get('/posts/:id', 'PostController@show');

$router->dispatch();

Se você tiver um PostController.php:

<?php
class PostController {
    public function show($params) {
        $id = $params['id'];
        return "Exibindo post: $id";
    }
}

Conclusão

Aprendemos que um router eficaz repousa em três pilares: captura correta da requisição HTTP, armazenamento inteligente de rotas com suporte a parâmetros e execução flexível de callbacks. Um router simples como este é suficiente para aplicações MVP ou APIs REST básicas, servindo como fundação para entender como frameworks profissionais funcionam. Para produção, considere usar soluções estabelecidas, mas nunca subestime o valor de implementar um router from scratch para consolidar seu conhecimento.

Referências


Artigos relacionados