szenis/路由

一个小巧简单的PHP路由器

v2.0.3 2017-10-28 15:04 UTC

README

Latest Stable Version Total Downloads Build Status

更新从0.x或1.x版本将会破坏您的代码!升级前请阅读文档!

入门指南

步骤 1 - .htaccess文件 在您项目的根目录创建一个 .htaccess文件并填写以下代码

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Redirect Trailing Slashes...
    RewriteRule ^(.*)/$ /$1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

步骤 2 - require szenis/routing
在您的终端执行: composer require szenis/routing

步骤 3 - 创建index.php
在您项目的根目录创建文件index.php

步骤 4 - require autoload.php并使用Router

以下示例展示了如何使用路由器。

<?php

require './vendor/autoload.php';

use Szenis\Routing\Router;

$router = new Router();
$router->get('/{n:date}-{w:item}', function($date, $item) {
    return 'hello world';
});

$response = $router->resolve($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD']);

switch ($response['code']) {
    case \Szenis\Routing\Route::STATUS_NOT_FOUND:
        // render your 404 page here...
        break;
    
    case \Szenis\Routing\Route::STATUS_FOUND:
        // the router only resolves the route, here is an example how to execute the route.
        if ($response['handler'] instanceof \Closure) {
            echo call_user_func_array($response['handler'], $response['arguments']);
        }
        
        break;
}

添加到您的index.php中

可选
为了调试目的,请将以下代码添加到您的index.php中

error_reporting(E_ALL);
ini_set('display_errors', 1);

用法

/**
 * initialize the router class
 */
$router = new Router();

/**
 * Route matches the url '/' for the GET method
 */
$router->add('/', 'GET', function() {
    // the closure will be executed when route is triggerd and will return 'hello world'
    return 'hello world!'; 
});

/**
 * It is posible to add one or multiple wildcards in one route
 */
$router->add('/user/{id}', 'GET', function($id) {
    return $id;
});

/**
 * It is also posible to allow mulitple methods for one route (methods should be separated with a '|')
 */
$router->add('/user/{id}/edit', 'GET|POST', function($id) {
    return 'user id: '.$id;
});

/**
 * Or when u are using controllers in a namespace you could give the full path to a controller (controller::action)
 *
 * Since version 2.0 executing the handler is up to you.
 */
$router->add('/user/{id}/delete', 'DELETE', 'App\Controllers\UserController::delete');

/**
 * Since version 1.1 there are shortcut methods for get, post, put, patch, delete and any.
 * You can use them as follow
 */
$router->get('/example/get', function() {});        // Will match GET requests
$router->post('/example/post', function() {});      // Will match POST requests
$router->put('/example/put', function() {});        // Will match PUT requests
$router->patch('/example/patch', function() {});    // Will match PATCH requests
$router->delete('/example/delete', function() {});  // Will match DELETE requests
$router->any('/example/any', function() {});        // Will match GET, POST, PUT, PATCH, DELETE requests

/**
 * resolve the route and receive the response
 *
 * The response is an array with the following keys
 * - code (contains 200 if the route is found, else 404)
 * - handler (contains the handler, often a \Closure or full path to your controller action)
 * - arguments (contains the route arguments if any)
 */
$response = $router->resolve($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD']);

/**
 * To execute your route you have to do the following
 */

switch ($response['code']) {
    case \Szenis\Routing\Route::STATUS_NOT_FOUND:
        // render your 404 page here...
        break;
    
    case \Szenis\Routing\Route::STATUS_FOUND:
        // the router only resolves the route, here is an example how to execute the route.
        if ($response['handler'] instanceof \Closure) {
            echo call_user_func_array($response['handler'], $response['arguments']);
        }
        
        // if your handler is a full path to your function you could execute it with this:
        $className = substr($response['handler'], 0, strpos($response['handler'], '::'));
        $functionName = substr($response['handler'], strpos($response['handler'], '::') + 2);

        echo call_user_func_array(array((new $className), $functionName), $response['arguments']);

        break;
}

通配符选项

以下选项存在
  • a:(仅字母字符)
  • n:(仅数字)
  • an:(仅字母数字字符)
  • w:(仅字母数字、破折号和下划线)
  • ?:(可选参数)-必须是URL的最后一部分
  • *:(懒加载)-必须是URL的最后一部分

如何使用

// The id must be a number
$router->add('/user/{n:id}', 'GET', 'App\Controllers\UserController::show');

// The id must contain either alfabetic chars or numbers
$router->add('/user/{an:id}', 'GET', 'App\Controllers\UserController::show');

// Now we want everything behind docs/ in the page variable
// For example when we go to the url /docs/user/edit we will receive user/edit in the page variable
$router->add('/docs/{*:page}', 'GET', function($page) {
    // do something with $page
});

// Optional parameter example
$router->add('/hello/{a:name}/{?:lastname}', 'GET', function($name, $lastname = null) {
    // check if lastname is provided
    // if ($lastname) {...}
})

从v0.x/v1.x升级到v2.x

  • 命名空间已从\Szenis更改为\Szenis\Routing
  • $router->setNamespace()已被删除!
  • RouteResolver不应用于解析路由,请使用以下代替:$router->resolve($uri, $method);
  • 路由器不再执行路由。从现在起,执行处理器的责任由您承担。在“用法”部分的底部有一个执行处理器的示例。

变更日志

v2.0.0

  • 移除了'default'命名空间
  • 命名空间从\Szenis更改为\Szenis\Routing
  • 路由器不再自行执行可调用对象,这为您提供了更多参数注入的控制权
  • RouteResolver可通过路由器调用
  • 修复了bug:现在可以在一个段中拥有多个参数(/{参数1}-{参数2}/)

v1.1.0

  • 为get、post、put、patch、delete和any提供了快捷函数

v1.0.0

  • 更新了README
  • 可能添加默认命名空间

v0.9.0

  • 100%测试覆盖率
  • 最低PHP版本从5.4降低到5.3

v0.8.0

  • 添加了可选参数
  • 添加了懒加载URL
  • 改进了代码

v0.7.0

  • 改进了代码

v0.6.0

  • 更改了路由器的用法,请查看用法部分以获取更多详细信息
  • 可能将闭包添加到路由器
  • 现在可以找到带有查询字符串的路由器(bug修复:v0.6.1)

v0.5.0

  • 移除了不必要的代码

v0.4.0

  • 添加了接口并创建了一个URL工厂

v0.3.0

  • 现在可以为URL通配符添加选项,有关更多信息请参阅通配符选项

v0.2.0

  • RouteResolver使用正则表达式来更快地匹配路由器