edifonttes/php-router 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

edifonttes/php-router

最新稳定版本:v2.2.0

Composer 安装命令:

composer require edifonttes/php-router

包简介

Sistema de roteamento PHP simples, poderoso e flexível com suporte a grupos, middlewares e parâmetros dinâmicos

README 文档

README

Sistema de roteamento PHP moderno, poderoso e flexível com suporte a middlewares, namespace dinâmico, proteção de rotas e muito mais.

PHP Version License

🚀 Características

  • ✅ Suporte a todos os métodos HTTP (GET, POST, PUT, DELETE, PATCH)
  • ✅ Parâmetros dinâmicos e opcionais nas rotas
  • ✅ Grupos de rotas com prefixos e namespaces
  • Sistema completo de middlewares (Auth, Admin, CRON, CORS, etc)
  • Namespace dinâmico para controllers
  • ✅ Rotas nomeadas
  • ✅ Suporte a closures e controllers
  • ✅ Separador customizável (::, @, :, etc)
  • ✅ Grupos aninhados ilimitados
  • Suporte a subdiretórios (aplicações em /subpasta)
  • Proteção de rotas CRON com tokens configuráveis
  • ✅ Zero dependências externas

📦 Instalação

composer require edifonttes/php-router

🎯 Início Rápido

Configuração Básica

<?php

require 'vendor/autoload.php';

use PHPRouter\Router;
use PHPRouter\Dispatcher;

$router = new Router();

// Define namespace padrão
$router->namespace('App\Controllers');

// Rota simples
$router->get('/', 'HomeController::index');

// Rota com parâmetro
$router->get('/users/{id}', 'UserController::show');

// Despacha a requisição
$dispatcher = new Dispatcher($router);
$dispatcher->dispatch();

.htaccess (Apache)

RewriteEngine On
RewriteBase /

# Redireciona tudo para index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

Para aplicações em subdiretórios (ex: /meuapp):

RewriteEngine On
RewriteBase /meuapp/

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

📚 Documentação Completa

Métodos HTTP

$router->get('/users', 'UserController::index');
$router->post('/users', 'UserController::store');
$router->put('/users/{id}', 'UserController::update');
$router->delete('/users/{id}', 'UserController::destroy');
$router->patch('/users/{id}', 'UserController::patch');

// Múltiplos métodos
$router->match(['GET', 'POST'], '/form', 'FormController::handle');

// Todos os métodos
$router->any('/webhook', 'WebhookController::handle');

Parâmetros de Rota

// Parâmetro obrigatório
$router->get('/users/{id}', function($id) {
    echo "User: " . $id;
});

// Múltiplos parâmetros
$router->get('/posts/{category}/{id}', function($category, $id) {
    echo "Category: {$category}, ID: {$id}";
});

// Parâmetro opcional
$router->get('/blog/{page?}', function($page = 1) {
    echo "Page: {$page}";
});

🎨 Namespace para Controllers

Problema resolvido: Não precisa mais escrever o namespace completo em cada rota!

// Define namespace base
$router->namespace('App\Controllers');

// Agora basta usar o nome da classe
$router->get('/', 'HomeController::index');
// Busca: App\Controllers\HomeController

$router->get('/about', 'HomeController::about');
// Busca: App\Controllers\HomeController

Mudando namespace ao longo do arquivo:

// Rotas públicas
$router->namespace('App\Controllers\Public');
$router->get('/blog', 'BlogController::index');
// Busca: App\Controllers\Public\BlogController

// Rotas admin
$router->namespace('App\Controllers\Admin');
$router->get('/admin', 'DashboardController::index');
// Busca: App\Controllers\Admin\DashboardController

Namespace em grupos:

$router->namespace('App\Controllers');

$router->group(['prefix' => 'admin', 'namespace' => 'Admin'], function($router) {
    $router->get('/', 'DashboardController::index');
    // Busca: App\Controllers\Admin\DashboardController
    
    $router->get('/users', 'UsersController::index');
    // Busca: App\Controllers\Admin\UsersController
});

Grupos aninhados:

$router->namespace('App\Controllers');

$router->group(['prefix' => 'api', 'namespace' => 'Api'], function($router) {
    
    $router->group(['prefix' => 'v1', 'namespace' => 'V1'], function($router) {
        $router->get('/users', 'UserController::index');
        // Busca: App\Controllers\Api\V1\UserController
    });
    
    $router->group(['prefix' => 'v2', 'namespace' => 'V2'], function($router) {
        $router->get('/users', 'UserController::index');
        // Busca: App\Controllers\Api\V2\UserController
    });
});

Ignorar namespace (usar FQCN):

$router->namespace('App\Controllers');

// Use \ no início para namespace absoluto
$router->get('/special', '\My\Custom\Controller::index');
// Busca EXATAMENTE: My\Custom\Controller

// Ou use namespace completo
$router->get('/other', 'Other\Package\Controller::index');
// Busca: Other\Package\Controller (detecta \ e ignora namespace definido)

Formatos de Handler

// Closure
$router->get('/', function() {
    echo "Home";
});

// Controller::class, 'method'
$router->get('/users', UserController::class, 'index');

// Array [Controller::class, 'method']
$router->get('/users', [UserController::class, 'index']);

// String com separador padrão (::)
$router->get('/users', 'UserController::index');

// Separador customizado
$router->setSeparator('@');
$router->get('/users', 'UserController@index');

$router->setSeparator(':');
$router->get('/users', 'UserController:index');

Grupos de Rotas

// Grupo com prefixo
$router->group(['prefix' => 'admin'], function($router) {
    // GET /admin/dashboard
    $router->get('/dashboard', 'AdminController::dashboard');
});

// Grupo com middleware
$router->group(['middleware' => 'auth'], function($router) {
    $router->get('/dashboard', 'DashboardController::index');
});

// Grupo com prefixo, namespace e middleware
$router->group([
    'prefix' => 'admin',
    'namespace' => 'Admin',
    'middleware' => ['auth', 'admin']
], function($router) {
    $router->get('/', 'DashboardController::index');
    // Rota: /admin
    // Controller: App\Controllers\Admin\DashboardController
    // Middlewares: auth, admin
});

🛡️ Sistema de Middlewares

Middlewares Incluídos

O router já vem com middlewares prontos para uso:

  1. AuthMiddleware - Protege rotas que requerem autenticação
  2. AdminMiddleware - Garante que apenas admins acessem
  3. GuestMiddleware - Permite acesso apenas para NÃO autenticados
  4. CronMiddleware - Protege rotas de CRON Jobs com tokens
  5. RefererMiddleware - Valida origem da requisição
  6. CorsMiddleware - Configura CORS para APIs

Registrando Middlewares

use PHPRouter\MiddlewareManager;
use PHPRouter\Middlewares\AuthMiddleware;
use PHPRouter\Middlewares\AdminMiddleware;
use PHPRouter\Middlewares\CronMiddleware;

// Registrar individualmente
MiddlewareManager::register('auth', AuthMiddleware::class);
MiddlewareManager::register('admin', AdminMiddleware::class);

// Ou múltiplos de uma vez
MiddlewareManager::registerMultiple([
    'auth' => AuthMiddleware::class,
    'admin' => AdminMiddleware::class,
    'cron' => CronMiddleware::class,
]);

Usando Middlewares

Em rotas individuais:

$router->get('/dashboard', 'DashboardController::index')->middleware('auth');

$router->get('/admin', 'AdminController::index')->middleware(['auth', 'admin']);

Em grupos:

$router->group(['middleware' => 'auth'], function($router) {
    $router->get('/dashboard', 'DashboardController::index');
    $router->get('/profile', 'ProfileController::show');
});

// Múltiplos middlewares
$router->group(['middleware' => ['auth', 'admin']], function($router) {
    $router->get('/admin', 'AdminController::index');
});

AuthMiddleware - Autenticação

Protege rotas que requerem usuário logado.

MiddlewareManager::register('auth', AuthMiddleware::class);

$router->get('/dashboard', 'DashboardController::index')->middleware('auth');

Funcionamento:

  • Verifica se $_SESSION['user_authenticated'] é true
  • Redireciona para /login se não autenticado
  • Retorna JSON para requisições AJAX

Para fazer login:

session_start();
$_SESSION['user_authenticated'] = true;
$_SESSION['user_id'] = $userId;
$_SESSION['user_name'] = $userName;
$_SESSION['user_role'] = 'user'; // ou 'admin'

AdminMiddleware - Apenas Administradores

Garante que apenas usuários com role de admin acessem.

$router->group(['middleware' => ['auth', 'admin']], function($router) {
    $router->get('/admin', 'AdminController::index');
});

Funcionamento:

  • Verifica se $_SESSION['user_role'] é 'admin'
  • Aborta com erro 403 se não for admin

GuestMiddleware - Apenas Não Autenticados

Útil para páginas de login/registro (usuários já logados são redirecionados).

$router->group(['middleware' => 'guest'], function($router) {
    $router->get('/login', 'AuthController::loginForm');
    $router->get('/register', 'AuthController::registerForm');
});

Funcionamento:

  • Redireciona para /dashboard se já autenticado
  • Permite acesso se NÃO autenticado

🔐 CronMiddleware - Proteção de Tarefas Agendadas

Protege rotas de CRON Jobs com autenticação por token.

Configuração Básica

1. Configure o token no .env:

CRON_TOKEN=b3a5514697975e4daa19757391df83ce //Atenção//, não use este token, ele está aqui apenas como exemplo. Gere o seu token digitando, php -r "echo bin2hex(random_bytes(16));" no CMD ou no Power Shell.

2. Registre e use:

MiddlewareManager::register('cron', CronMiddleware::class);

$router->group(['prefix' => 'cron', 'middleware' => 'cron'], function($router) {
    $router->get('/daily-cleanup', 'CronController::dailyCleanup');
    $router->get('/send-emails', 'CronController::sendEmails');
});

3. Teste:

# Via Header
curl -H "X-Cron-Auth: b3a5514697975e4daa19757391df83ce" http://localhost/cron/daily-cleanup

# Via Bearer Token
curl -H "Authorization: Bearer b3a5514697975e4daa19757391df83ce" http://localhost/cron/daily-cleanup

# Via Query String
curl "http://localhost/cron/daily-cleanup?cron_token=b3a5514697975e4daa19757391df83ce"

Configurações Avançadas

Middleware que aceita APENAS header:

$cronHeader = (new CronMiddleware())
    ->setEnvVar('CRON_TOKEN')
    ->setHeaderName('X-Cron-Auth')
    ->setAuthType('header');

MiddlewareManager::register('cron-header', get_class($cronHeader));

$router->get('/cron/backup', 'CronController::backup')->middleware('cron-header');

Middleware que aceita APENAS Bearer:

$cronBearer = (new CronMiddleware())
    ->setEnvVar('BACKUP_TOKEN')
    ->setAuthType('bearer');

$router->get('/backup/full', 'BackupController::full')->middleware([$cronBearer]);

Middleware que aceita APENAS Query String:

$cronQuery = (new CronMiddleware())
    ->setEnvVar('WEBHOOK_TOKEN')
    ->setAuthType('query')
    ->setQueryParam('token');

$router->post('/webhook/payment', 'WebhookController::handle')->middleware([$cronQuery]);

Tokens diferentes para tarefas diferentes:

# .env
CRON_TOKEN=b3a5514697975e4daa19757391df83ce
BACKUP_TOKEN=abc123def456
WEBHOOK_TOKEN=xyz789uvw456
// Tarefa diária
$cronDaily = (new CronMiddleware())->setEnvVar('CRON_TOKEN');
$router->get('/cron/daily', 'CronController::daily')->middleware([$cronDaily]);

// Backup
$cronBackup = (new CronMiddleware())->setEnvVar('BACKUP_TOKEN');
$router->get('/cron/backup', 'CronController::backup')->middleware([$cronBackup]);

// Webhook
$cronWebhook = (new CronMiddleware())->setEnvVar('WEBHOOK_TOKEN');
$router->post('/webhook/payment', 'WebhookController::payment')->middleware([$cronWebhook]);

Tipos de Autenticação

Tipo Descrição Uso
'any' Aceita header, bearer OU query (padrão) Máxima flexibilidade
'header' Apenas header customizado Servidores que suportam headers
'bearer' Apenas Authorization Bearer APIs modernas
'query' Apenas query string Servidores limitados

Métodos de Configuração

$middleware = (new CronMiddleware())
    ->setToken('abc123')              // Define token manualmente
    ->setEnvVar('MY_TOKEN')            // Lê do .env
    ->setHeaderName('X-My-Auth')       // Nome do header
    ->setAuthType('header')            // Tipo de auth
    ->setQueryParam('api_key')         // Nome do parâmetro query
    ->setAllowCli(true);               // Permite via terminal

Configurando no Crontab

# Opção 1: Header (recomendado)
0 2 * * * curl -H "X-Cron-Auth: TOKEN" https://seusite.com/cron/daily

# Opção 2: Bearer
0 2 * * * curl -H "Authorization: Bearer TOKEN" https://seusite.com/cron/daily

# Opção 3: Query String (se servidor não suportar headers)
0 2 * * * curl "https://seusite.com/cron/daily?cron_token=TOKEN"

CorsMiddleware - APIs com CORS

MiddlewareManager::register('cors', CorsMiddleware::class);

$router->group(['prefix' => 'api', 'middleware' => 'cors'], function($router) {
    $router->get('/users', 'ApiController::users');
});

Customizando:

$cors = (new CorsMiddleware())
    ->setAllowedOrigins(['https://meuapp.com', 'https://app.example.com'])
    ->setAllowedMethods(['GET', 'POST', 'PUT', 'DELETE'])
    ->setAllowCredentials(true);

RefererMiddleware - Validação de Origem

$referer = new RefererMiddleware(['meusite.com', 'api.meusite.com']);

$router->post('/webhook', 'WebhookController::handle')->middleware([$referer]);

Criando Middleware Customizado

<?php

namespace App\Middlewares;

use PHPRouter\Middleware;

class RateLimitMiddleware extends Middleware
{
    public function handle(callable $next)
    {
        $ip = $_SERVER['REMOTE_ADDR'];
        
        // Sua lógica aqui
        if ($this->exceedsLimit($ip)) {
            $this->json(['error' => 'Rate limit exceeded'], 429);
        }
        
        return $next();
    }
    
    private function exceedsLimit($ip) {
        // Implementar lógica de rate limiting
        return false;
    }
}

📝 Rotas Nomeadas

// Definir rota nomeada
$router->get('/users/{id}', 'UserController::show')->name('users.show');

// Gerar URL
$url = $router->route('users.show', ['id' => 123]);
// Resultado: /users/123

🎛️ Handlers Customizados

$dispatcher = new Dispatcher($router);

// Handler 404 customizado
$dispatcher->setNotFoundHandler(function() {
    http_response_code(404);
    echo "<h1>404 - Página não encontrada</h1>";
});

// Handler de erro customizado
$dispatcher->setErrorHandler(function($e) {
    http_response_code(500);
    echo "<h1>Erro: " . htmlspecialchars($e->getMessage()) . "</h1>";
});

$dispatcher->dispatch();

💡 Exemplos Práticos

Landing Page + Painel Admin

$router->namespace('App\Controllers');

// Landing page (público)
$router->get('/', 'HomeController::index');
$router->get('/about', 'HomeController::about');
$router->get('/pricing', 'HomeController::pricing');

// Login/Registro (apenas não logados)
$router->group(['middleware' => 'guest', 'namespace' => 'Auth'], function($router) {
    $router->get('/login', 'AuthController::loginForm');
    $router->post('/login', 'AuthController::login');
    $router->get('/register', 'AuthController::registerForm');
});

// Dashboard (autenticado)
$router->group([
    'prefix' => 'dashboard',
    'middleware' => 'auth',
    'namespace' => 'User'
], function($router) {
    $router->get('/', 'DashboardController::index');
    $router->get('/profile', 'ProfileController::show');
});

// Admin (autenticado + admin)
$router->group([
    'prefix' => 'admin',
    'middleware' => ['auth', 'admin'],
    'namespace' => 'Admin'
], function($router) {
    $router->get('/', 'AdminController::index');
    $router->get('/users', 'AdminController::users');
});

API REST Completa

$router->namespace('App\Controllers');

$router->group([
    'prefix' => 'api/v1',
    'middleware' => 'cors',
    'namespace' => 'Api\V1'
], function($router) {
    
    // Rotas públicas
    $router->post('/login', 'AuthController::login');
    $router->get('/products', 'ProductController::index');
    
    // Rotas protegidas
    $router->group(['middleware' => 'auth'], function($router) {
        $router->get('/user', 'UserController::current');
        $router->post('/orders', 'OrderController::create');
        $router->get('/orders', 'OrderController::myOrders');
    });
});

Sistema com CRON Jobs

$router->namespace('App\Controllers');

// Rotas web normais
$router->get('/', 'HomeController::index');

// CRON Jobs protegidos
MiddlewareManager::register('cron', CronMiddleware::class);

$router->group([
    'prefix' => 'cron',
    'middleware' => 'cron',
    'namespace' => 'Cron'
], function($router) {
    $router->get('/daily-cleanup', 'CronController::dailyCleanup');
    $router->get('/send-emails', 'CronController::sendEmails');
    $router->get('/backup', 'CronController::backup');
});

⚙️ Configuração do .env

# ============================================
# APLICAÇÃO
# ============================================
APP_NAME="Minha Aplicação"
APP_ENV=development  # development, production
APP_DEBUG=true

# ============================================
# TOKENS DE SEGURANÇA
# ============================================
# Token para CRON Jobs (gere com: openssl rand -hex 32)
CRON_TOKEN=b3a5514697975e4daa19757391df83ce

# Tokens específicos
BACKUP_TOKEN=abc123def456
WEBHOOK_TOKEN=xyz789uvw456

# ============================================
# CONFIGURAÇÕES DE SESSÃO
# ============================================
SESSION_LIFETIME=120
AUTH_SESSION_KEY=user_authenticated

📁 Estrutura Recomendada

seu-projeto/
├── public/
│   ├── index.php
│   ├── .htaccess
│   ├── css/
│   └── js/
├── app/
│   ├── Controllers/
│   │   ├── HomeController.php
│   │   ├── Auth/
│   │   │   └── AuthController.php
│   │   ├── User/
│   │   │   └── DashboardController.php
│   │   ├── Admin/
│   │   │   └── AdminController.php
│   │   └── Api/
│   │       └── V1/
│   │           └── UserController.php
│   └── Middlewares/
│       └── CustomMiddleware.php
├── vendor/
├── .env
└── composer.json

public/index.php

<?php
ob_start();

require __DIR__ . '/../vendor/autoload.php';

use PHPRouter\Router;
use PHPRouter\Dispatcher;
use PHPRouter\MiddlewareManager;
use PHPRouter\Middlewares\AuthMiddleware;
use PHPRouter\Middlewares\AdminMiddleware;
use PHPRouter\Middlewares\CronMiddleware;

// Registrar middlewares
MiddlewareManager::registerMultiple([
    'auth' => AuthMiddleware::class,
    'admin' => AdminMiddleware::class,
    'cron' => CronMiddleware::class,
]);

// Criar router
$router = new Router();
$router->setSeparator(':');
$router->namespace('App\Controllers');

// Definir rotas
require __DIR__ . '/../routes/web.php';
require __DIR__ . '/../routes/api.php';

// Despachar
$dispatcher = new Dispatcher($router);
$dispatcher->setNotFoundHandler(function() {
    http_response_code(404);
    require __DIR__ . '/../views/errors/404.php';
});
$dispatcher->dispatch();

ob_end_flush();

🔍 Métodos Úteis

// Listar todas as rotas (debug)
$routes = $router->listRoutes();
print_r($routes);

// Obter namespace atual
$namespace = $router->getNamespace();

// Obter separador atual
$separator = $router->getSeparator();

// Verificar middlewares registrados
$aliases = MiddlewareManager::getAliases();
$globals = MiddlewareManager::getGlobals();

🚨 Troubleshooting

Erro 404 em todas as rotas

  • Verifique se o .htaccess está correto
  • Verifique se mod_rewrite está habilitado no Apache
  • Para subdiretórios, ajuste o RewriteBase

Middleware não está funcionando

  • Certifique-se de registrar ANTES de usar
  • Verifique se aplicou na rota ou grupo
  • Verifique a ordem dos middlewares

Sessão não persiste

  • Verifique configurações de sessão no php.ini
  • Certifique-se que session_start() é chamado
  • Em desenvolvimento, verifique domínio/path dos cookies

CRON retorna 403

  • Verifique se o token no .env está correto
  • Teste manualmente com CURL
  • Verifique se o tipo de auth está correto (header, bearer, query)

Namespace não funciona

  • Certifique-se que o autoload do Composer está correto
  • Rode composer dump-autoload
  • Verifique se o namespace da classe corresponde ao configurado

🤝 Contribuindo

Contribuições são bem-vindas! Por favor:

  1. Fork o projeto
  2. Crie uma branch para sua feature (git checkout -b feature/MinhaFeature)
  3. Commit suas mudanças (git commit -m 'Adiciona MinhaFeature')
  4. Push para a branch (git push origin feature/MinhaFeature)
  5. Abra um Pull Request

📄 Licença

Este projeto está sob a licença MIT. Veja o arquivo LICENSE para mais detalhes.

👨‍💻 Créditos

Desenvolvido por Edivan B. Fontes

💬 Suporte

⭐ Se este projeto te ajudou, considere dar uma estrela no GitHub!

统计信息

  • 总下载量: 6
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-11-18