此包已被弃用且不再维护。未建议替代包。

小型PHP路由器

5.4.0 2019-10-29 23:20 UTC

README

Build Status Scrutinizer Code Quality Coverage Status

什么是Saffron?

Saffron是一款非常快速灵活的PHP路由器,适用于您的应用程序。

版本

我不再用PHP开发软件,因此不再积极支持此项目。最近由于贡献项目的更新,以确保与PHP 7.x兼容,最新标签支持旧版PHP版本(以及HHVM)是5.3。如果您仍然使用此项目,欢迎贡献。

功能

  • 无外部依赖
  • 高性能
  • 方法条件支持
  • 域名条件支持
  • HTTPS/非HTTPS条件支持
  • 带可选参数的路由
  • 参数要求
  • 反向路由
  • 经过良好测试,100%测试覆盖率

安装

您可以通过在composer.json中添加以下要求轻松安装Saffron

{
    "require": {
        "krzysztof-magosa/saffron": "5.*"
    }
}

如何使用

您需要使用RouterFactory来创建Router实例。RouterFactory构造函数接受一个参数,即配置路由的闭包。闭包接收RoutesCollection作为第一个参数。闭包只会触发一次,然后所有内容都会存储在编译文件中。

use KM\Saffron\RouterFactory;

$factory = new RouterFactory(
    function ($collection) {
        // configuration of routes goes here...
        $collection->route('home')
            ->setUri('/')
            ->setTarget('HomeController');
    }
);

默认情况下,Saffron将缓存存储在系统临时目录中。为了避免在相同服务器上托管的项目之间的冲突,建议为每个项目设置单独的缓存目录。如果您确实需要为多个项目使用同一个目录,可以设置类后缀。

$factory
    ->setCacheDir(__DIR__ . '/cache')
    ->setClassSuffix('MyProject')
    ->build();

配置RouterFactory后,您可以通过调用build()方法来构建Router实例。

$router = $factory->build();

配置路由

use KM\Saffron\RouterFactory;

$factory = new RouterFactory(
    function ($collection) {
        $collection->route('home')
            ->setUri('/')
            ->setTarget('HomeController');
            
        $collection->route('contact')
            ->setUri('/contact')
            //...
            ->setTarget('ContactController');
            
        //...
    }
);

要添加路由,您需要在$collection上调用route()方法,将路由名称作为第一个参数。该方法返回Route实例,然后您可以在其上设置参数。您可以创建任意数量的路由,但每个都需要有唯一名称。

设置目标

为了在匹配特定路由后执行控制器,您需要使用setTarget()方法。第一个参数是控制器的类名,第二个参数是方法名。如果您省略第二个参数,它将默认为'indexAction'。

$collection->route('home')
    ->setTarget('HomeController');

$collection->route('team')
    ->setTarget('TeamController', 'actionName');

设置URI

为了将请求与URI匹配,您需要在Route实例上调用setUri()方法。它只接受一个参数,即预期的URI。

$collection->route('contact')
    ->setUri('/contact');

设置域名

为了将请求与域名匹配,您需要在Route实例上调用setDomain()方法。它只接受一个参数,即预期的域名。

$collection->route('contact')
    ->setDomain('www.example.com');

设置方法

为了将请求与方法匹配,您需要在路由实例上调用 setMethod() 方法。您可以传递一个字符串作为方法,或使用数组传递多个方法。

$collection->route('api1')
    ->setMethod('GET');

$collection->route('api2')
    ->setMethod(['GET', 'POST']);

设置 https

您可能只想通过加密或未加密的连接访问某些资源。可以使用 setHttps() 方法实现。如果只想允许加密流量,则传递 true;如果允许未加密流量,则传递 false。null 表示无关紧要(这是默认设置)。

$collection->route('secret')
    ->setHttps(true);
    
$collection->route('public')
    ->setHttps(false);

使用占位符

如果您的 uri 或域名包含可变部分,您可以使用占位符来捕获它们。占位符使用大括号定义。

$collection->route('contact')
    ->setUri('/contact/{name}')
    ->setDomain('{lang}.example.com');

此示例允许您使用如下链接

有时您想允许用户在链接中省略一些占位符。您可以使用 setDefaults() 方法来实现这一点。

$collection->route('contact')
    ->setUri('/contact/{name}')
    ->setDomain('{lang}.example.com')
    ->setDefaults(
        [
            'name' => 'webmaster',
            'lang' => 'english',
        ]
    );

现在用户可以进入以下链接 http://example.com/contact,lang 将为 'english',name 将为 'webmaster'。

您还可以设置占位符的要求,以便用户只能使用某些值。要求是使用正则表达式构建的,与 preg_match() 中使用的相同。

$collection->route('contact')
    ->setUri('/contact/{name}')
    ->setDomain('{lang}.example.com')
    ->setDefaults(
        [
            'name' => 'webmaster',
            'lang' => 'english',
        ]
    )
    ->setRequirements(
        [
            'name' => '\w+',
            'lang' => 'english|spanish|french',
        ]
    );

匹配请求

Saffron 接受 Request 对象。在典型配置中,您可以使用 createFrom Globals() 静态方法。它在 Apache 服务器和 mod_php 上进行了测试。

use KM\Saffron\Request;
$request = Request::createFromGlobals();

如果您的配置不典型,您可以手动创建此对象。

use KM\Saffron\Request;
$request = new Request();
$request
    ->setUri($uri)
    ->setDomain($domain)
    ->setMethod($method)
    ->setHttps($https);

现在您可以将此对象传递给 Router 的 match() 方法,该方法返回 RoutingResult 对象。

$result = $router->match($request);

您可以使用 isSuccessful() 方法检查匹配是否成功。要检查匹配失败的原因,您需要使用两个方法:isResourceNotFound() 和 isMethodNotAllowed()。当 isResourceNotFound() 返回 true 时,您应向用户显示错误 404;当 isMethodNotAllowed() 返回 true 时,您应显示错误 405。RFC 2616 要求在显示 405 错误时设置包含允许方法的 Allow 标头。您可以通过调用 getAllowedMethods() 获取此列表。请记住,Saffron 不是框架,而只是路由器,因此这是由您来做的。

构建链接

Saffron 是双向路由器,因此除了匹配请求外,您还可以构建链接。路由器有 assemble() 方法用于构建链接。

// Building uri
$uri = $router->assemble('routeName', ['parameter1' => 'value1']);

// Building entire link (scheme + domain + uri)
$link = $router->assemble('routeName', ['parameter1' => 'value1'], true);

执行控制器

在成功匹配请求后,您可以使用 Executor 触发路由中指定的控制器。

use KM\Saffron\Executor;
$executor = new Executor($result);
$executor->fire();

在某些情况下,需要在执行操作之前或之后对控制器进行一些操作。这可以通过使用 setPreDispatch() 和 setPostDispatch() 来实现。

use KM\Saffron\Executor;
$executor = new Executor($result);
$executor
    ->setPreDispatch(
        function ($controller, $method, $parameters) {
            // do something before calling action
        }
    )
    ->setPostDispatch(
        function ($controller, $method, $parameters) {
            // do something after calling action
        }
    );

$executor->fire();

在某些情况下(例如触发错误控制器),您可能想触发不是来自匹配路由的控制器。Executor 也支持这种情况。

$executor = new Executor();
$executor
    ->setController('YourController')
    ->setMethod('methodName')
    ->setParameters(['param1' => 'value1'])
    ->fire();

获取参数

如果您的 uri 或域名包含占位符,它们将被作为参数传递给您的控制器的方法。您只需确保控制器方法具有与您的占位符相同名称的参数即可。您不需要捕获所有占位符。

class Controller
{
    public function method($lang, $name)
    {
    }
}