<h2>O que é Roteamento HTTP e Por Que Importa</h2>
<p>Roteamento HTTP é o mecanismo fundamental que mapeia URLs para ações específicas em sua aplicação. Quando um usuário acessa <code>exemplo.com/usuarios/123</code>, 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.</p>
<p>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.</p>
<h2>Fundamentos: Como um Router Funciona</h2>
<h3>Capturando a URL e o Método HTTP</h3>
<p>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:</p>
<pre><code class="language-php"><?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];
}
}</code></pre>
<p>Este código extrai o método HTTP (GET, POST, PUT, DELETE) e o caminho limpo. A função <code>parse_url()</code> garante que parâmetros query sejam ignorados, mantendo apenas a estrutura da rota.</p>
<h3>Registrando Rotas</h3>
<p>Agora precisamos de um sistema para registrar rotas e associá-las a callbacks:</p>
<pre><code class="language-php">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;
}</code></pre>
<p>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.</p>
<h2>Implementação: Criando um Router Completo</h2>
<h3>Suportando Rotas Dinâmicas com Parâmetros</h3>
<p>Rotas estáticas são úteis, mas a maioria das aplicações precisa de parâmetros dinâmicos. Vamos adicionar suporte a <code>:id</code> e similares:</p>
<pre><code class="language-php">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;
}</code></pre>
<p>Este método usa regex para transformar rotas como <code>/usuarios/:id</code> em padrões capturáveis. Se encontrar uma correspondência, retorna o callback e um array com os parâmetros extraídos.</p>
<h3>Executando o Router</h3>
<p>Agora vamos adicionar o método que executa toda a lógica:</p>
<pre><code class="language-php">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));
}
}</code></pre>
<h2>Exemplo Prático: Usando o Router</h2>
<h3>Aplicação Completa Funcionando</h3>
<pre><code class="language-php"><?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();</code></pre>
<p>Se você tiver um <code>PostController.php</code>:</p>
<pre><code class="language-php"><?php
class PostController {
public function show($params) {
$id = $params['id'];
return "Exibindo post: $id";
}
}</code></pre>
<h2>Conclusão</h2>
<p>Aprendemos que um router eficaz repousa em três pilares: <strong>captura correta da requisição HTTP</strong>, <strong>armazenamento inteligente de rotas com suporte a parâmetros</strong> e <strong>execução flexível de callbacks</strong>. 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.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://www.php.net/manual/en/reserved.variables.server.php" target="_blank" rel="noopener noreferrer">PHP Manual: $_SERVER Superglobal</a></li>
<li><a href="https://www.php-fig.org/psr/psr-7/" target="_blank" rel="noopener noreferrer">PSR-7: HTTP Message Interface</a></li>
<li><a href="https://github.com/nikic/FastRoute" target="_blank" rel="noopener noreferrer">FastRoute: Roteador de Alto Desempenho</a></li>
<li><a href="https://laravel.com/docs/routing" target="_blank" rel="noopener noreferrer">Laravel Routing Documentation</a></li>
<li><a href="https://www.php.net/manual/en/intro.http.php" target="_blank" rel="noopener noreferrer">RESTful APIs com PHP</a></li>
</ul>