israel-nogueira/fast-router 问题修复 & 功能扩展

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

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

israel-nogueira/fast-router

Composer 安装命令:

composer require israel-nogueira/fast-router

包简介

Modern, fast and flexible PHP router with support for static and instance modes, middleware chains, and advanced routing features

README 文档

README

Latest Version Total Downloads License PHP Version

Modern, fast and flexible PHP router with support for static and instance modes, middleware chains, route groups, and advanced routing features.

✨ Features

  • Dual Mode: Static (auto-dispatch) and Instance (manual control)
  • Route Parameters: Simple {id} and regex {id:\d+} with optional parameters
  • Route Groups: Nested groups with prefix and middleware inheritance
  • Middleware Chain: Elegant middleware system with dependency injection
  • Multiple HTTP Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS, ANY, and custom
  • Controller Support: String syntax, array syntax, and closures
  • Named Routes: Reference routes by name (coming soon)
  • PSR-4 Autoloading: Modern namespace structure
  • Type Safety: Full PHP 8.1+ type hints
  • Zero Dependencies: Standalone library
  • Debug Mode: Built-in debugging capabilities

📦 Installation

composer require israel-nogueira/fast-router

Requirements

  • PHP >= 8.1
  • Composer

🚀 Quick Start

Basic Usage

<?php

require 'vendor/autoload.php';

use IsraelNogueira\FastRouter\Router;

// Simple route
Router::get('/', function() {
    echo "Hello World!";
});

// Route with parameter
Router::get('user/{id}', function($id) {
    echo "User ID: {$id}";
});

// POST route
Router::post('contact', function() {
    echo "Form submitted!";
});

📚 Documentation

Table of Contents

🔄 Static vs Instance Mode

Static Mode (Auto-Dispatch)

Routes are automatically dispatched after each definition:

use IsraelNogueira\FastRouter\Router;

Router::get('/', function() {
    echo "Home";
});

Router::get('about', function() {
    echo "About";
});

// No need to call dispatch() - routes auto-execute

Instance Mode (Manual Control)

For more control, create a Router instance:

$router = new Router();

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

$router->get('about', function() {
    echo "About";
});

// Manually dispatch routes
$router->dispatch();

When to use each:

  • Static Mode: Simple applications, rapid prototyping
  • Instance Mode: Testing, multiple routers, advanced control

🎯 Route Parameters

Simple Parameters

Router::get('user/{id}', function($id) {
    echo "User: {$id}";
});

Router::get('post/{year}/{month}/{slug}', function($year, $month, $slug) {
    echo "Post: {$slug} from {$month}/{$year}";
});

Regex Constraints

// Only numbers
Router::get('product/{id:\d+}', function($id) {
    echo "Product: {$id}";
});

// Only lowercase letters and hyphens
Router::get('category/{slug:[a-z-]+}', function($slug) {
    echo "Category: {$slug}";
});

// Date pattern
Router::get('archive/{date:\d{4}-\d{2}-\d{2}}', function($date) {
    echo "Archive: {$date}";
});

Optional Parameters

// Single optional parameter
Router::get('blog/{id:\d+}[/{title}/]', function($id, $title = null) {
    echo "Blog: {$id}";
    if ($title) echo " - {$title}";
});

// Multiple optional parameters
Router::get('archive/{year:\d{4}}[/{month:\d{2}}[/{day:\d{2}}/]/]', 
    function($year, $month = null, $day = null) {
        echo "Archive: {$year}/{$month}/{$day}";
    }
);

Syntax Rules:

  • Required: {param} or {param:regex}
  • Optional: [/{param}/] with slashes inside brackets
  • Nested: [/{a}[/{b}/]/] for multiple optional params

📂 Route Groups

Simple Groups

Router::group('admin', function($router) {
    
    $router->get('dashboard', function() {
        echo "Admin Dashboard";
        // URL: /admin/dashboard
    });
    
    $router->get('users', function() {
        echo "Admin Users";
        // URL: /admin/users
    });
});

Nested Groups

Router::group('admin', function($router) {
    
    $router->group('products', function($router) {
        
        $router->get('list', function() {
            echo "Product List";
            // URL: /admin/products/list
        });
        
        $router->group('category', function($router) {
            
            $router->get('list', function() {
                echo "Category List";
                // URL: /admin/products/category/list
            });
        });
    });
});

Groups with Middleware

Router::group([
    'prefix' => 'admin',
    'middleware' => ['auth', 'admin']
], function($router) {
    
    $router->get('dashboard', function() {
        echo "Secure Dashboard";
    });
    
    $router->get('settings', function() {
        echo "Secure Settings";
    });
});

🛡️ Middleware

Middleware allows you to filter HTTP requests before they reach your route handler.

Creating Middleware

class AuthMiddleware
{
    public function handle(array $returns, callable $next): mixed
    {
        // Check authentication
        if (!isset($_SESSION['user'])) {
            http_response_code(401);
            die('Unauthorized');
        }
        
        // Add data to returns array
        $returns[] = [
            'middleware' => 'auth',
            'user' => $_SESSION['user']
        ];
        
        // Continue to next middleware
        return $next($returns);
    }
}

Using Middleware

On Single Routes

Router::get([
    'prefix' => 'dashboard',
    'middleware' => [AuthMiddleware::class]
], function() {
    echo "Protected Dashboard";
});

On Route Groups

Router::group([
    'prefix' => 'admin',
    'middleware' => [AuthMiddleware::class, LogMiddleware::class]
], function($router) {
    
    $router->get('users', function() {
        echo "Admin Users";
    });
    
    $router->get('settings', function() {
        echo "Admin Settings";
    });
});

String Syntax

Router::get([
    'prefix' => 'profile',
    'middleware' => ['App\Middleware\Auth@handle']
], function() {
    echo "User Profile";
});

Middleware Chain

Middlewares execute in order. Each middleware must call $next($returns) to continue:

class FirstMiddleware
{
    public function handle(array $returns, callable $next): mixed
    {
        echo "Before First\n";
        $result = $next($returns);
        echo "After First\n";
        return $result;
    }
}

class SecondMiddleware
{
    public function handle(array $returns, callable $next): mixed
    {
        echo "Before Second\n";
        $result = $next($returns);
        echo "After Second\n";
        return $result;
    }
}

// Output:
// Before First
// Before Second
// [Route Handler]
// After Second
// After First

Stopping the Chain

To stop execution, don't call $next():

class AdminCheckMiddleware
{
    public function handle(array $returns, callable $next): mixed
    {
        if (!$this->isAdmin()) {
            http_response_code(403);
            die('Forbidden');
            // Chain stops here
        }
        
        return $next($returns);
    }
}

🎮 Controllers

Controller Class

class UserController
{
    public function index()
    {
        echo "User List";
    }
    
    public function show($id)
    {
        echo "User: {$id}";
    }
    
    public function store()
    {
        echo "Create User";
    }
}

String Syntax

Router::get('users', 'UserController@index');
Router::get('users/{id}', 'UserController@show');
Router::post('users', 'UserController@store');

Array Syntax

Router::get('users', [UserController::class, 'index']);
Router::get('users/{id}', [UserController::class, 'show']);
Router::post('users', [UserController::class, 'store']);

Multiple Callbacks

Execute multiple callbacks in sequence:

Router::get('dashboard', [
    'logRequest',  // Function
    'UserController@auth',  // Controller method
    [DashboardController::class, 'index'],  // Array syntax
    function() {  // Closure
        echo " - Rendered";
    }
]);

RESTful Resource Routes

$resource = 'posts';
$controller = PostController::class;

Router::get($resource, [$controller, 'index']);           // GET /posts
Router::get("{$resource}/create", [$controller, 'create']); // GET /posts/create
Router::post($resource, [$controller, 'store']);          // POST /posts
Router::get("{$resource}/{id}", [$controller, 'show']);   // GET /posts/123
Router::get("{$resource}/{id}/edit", [$controller, 'edit']); // GET /posts/123/edit
Router::put("{$resource}/{id}", [$controller, 'update']); // PUT /posts/123
Router::delete("{$resource}/{id}", [$controller, 'destroy']); // DELETE /posts/123

🌐 HTTP Methods

Standard Methods

Router::get('/', fn() => 'GET');
Router::post('/', fn() => 'POST');
Router::put('/', fn() => 'PUT');
Router::delete('/', fn() => 'DELETE');
Router::patch('/', fn() => 'PATCH');
Router::options('/', fn() => 'OPTIONS');
Router::head('/', fn() => 'HEAD');

Any Method

Accepts all HTTP methods:

Router::any('search', function() {
    echo "Works with any HTTP method";
});

Multiple Specific Methods

// Using math() method
Router::math(['GET', 'POST'], 'form', function() {
    if ($_SERVER['REQUEST_METHOD'] === 'GET') {
        echo "Show form";
    } else {
        echo "Process form";
    }
});

Custom Methods

Router::addRoute(['CUSTOM', 'SPECIAL'], 'endpoint', function() {
    echo "Custom HTTP method";
});

🔧 Advanced Features

Continue to Next Route

By default, router stops after first match. To continue:

Router::get([
    'prefix' => 'log/{id}',
    'continue' => true
], function($id) {
    error_log("Logging access to: {$id}");
});

Router::get('log/{id}', function($id) {
    echo "Viewing log: {$id}";
});

Debug Mode

Enable debugging to see route matching process:

$router = new Router();
$router->debug(true);

$router->get('test', function() {
    echo "Test";
});

$router->dispatch();

// Output includes HTML comments:
// <!-- Fast Router Debug -->
// <!-- Method: GET -->
// <!-- URL: /test -->
// <!-- Routes: 1 -->
// <!-- Matched: test -->

Custom Dispatch

Test routes with custom URL and method:

$router = new Router();

$router->get('api/users/{id}', function($id) {
    return ['user_id' => $id];
});

// Dispatch with custom parameters
$result = $router->dispatch('GET', '/api/users/123');

Route Collection

Access registered routes:

$router = new Router();

$router->get('home', fn() => 'Home');
$router->get('about', fn() => 'About');

$collection = $router->getRoutes();
echo "Total routes: " . $collection->count();

foreach ($collection->all() as $route) {
    echo $route->pattern . "\n";
}

Clear Routes

$router = new Router();

$router->get('test1', fn() => 'Test 1');
$router->get('test2', fn() => 'Test 2');

// Clear all routes
$router->clear();

🧪 Testing

Unit Testing Example

use PHPUnit\Framework\TestCase;
use IsraelNogueira\FastRouter\Router;

class RouterTest extends TestCase
{
    public function testBasicRoute()
    {
        $router = new Router();
        
        $router->get('test', function() {
            return 'success';
        });
        
        $result = $router->dispatch('GET', '/test');
        
        $this->assertEquals('success', $result);
    }
    
    public function testRouteParameters()
    {
        $router = new Router();
        
        $router->get('user/{id:\d+}', function($id) {
            return $id;
        });
        
        $result = $router->dispatch('GET', '/user/123');
        
        $this->assertEquals('123', $result);
    }
}

📖 Migration from v1.x

Breaking Changes

  1. Namespace change: IsraelNogueira\fastRouterIsraelNogueira\FastRouter
  2. PHP requirement: Now requires PHP 8.1+
  3. Type hints: All methods now use strict types

Migration Steps

// OLD (v1.x)
use IsraelNogueira\fastRouter\router;

router::get('/', function() {});

// NEW (v2.x)
use IsraelNogueira\FastRouter\Router;

Router::get('/', function() {});

Good news: All public APIs remain compatible! Just update the namespace.

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Development Setup

git clone https://github.com/israel-nogueira/fast-router.git
cd fast-router
composer install

Running Tests

composer test

Code Quality

composer analyse

📄 License

This project is licensed under the GPL-3.0-or-later License - see the LICENSE file for details.

👤 Author

Israel Nogueira

🌟 Show Your Support

Give a ⭐️ if this project helped you!

📝 Changelog

v2.0.0 (2026-02-10)

  • ✨ Complete refactoring with modern PHP 8.1+ features
  • ✨ Added strict type hints throughout
  • ✨ Improved middleware system
  • ✨ Better error handling with custom exceptions
  • ✨ PSR-4 autoloading structure
  • ✨ Debug mode
  • 🐛 Fixed various edge cases in route matching
  • 📚 Complete documentation rewrite

v1.x

  • Initial releases with basic routing functionality

Made with ❤️ by Israel Nogueira

israel-nogueira/fast-router 适用场景与选型建议

israel-nogueira/fast-router 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 76 次下载、GitHub Stars 达 1, 最近一次更新时间为 2023 年 05 月 14 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「routing」 「php」 「http」 「router」 「middleware」 「fast-router」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 israel-nogueira/fast-router 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 israel-nogueira/fast-router 我们能提供哪些服务?
定制开发 / 二次开发

基于 israel-nogueira/fast-router 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: GPL-3.0-or-later
  • 更新时间: 2023-05-14