dev-lucid/router

一个简单的路由解析库。

2.0.0 2016-05-12 00:52 UTC

This package is not auto-updated.

Last update: 2024-09-14 19:31:04 UTC


README

这是一个几乎完全无需配置的极简路由器。我之所以编写这个路由器,是因为我认为现在的路由器似乎需要太多的配置。

在我看来,一个好的路由器应该做到以下几点,仅此而已

  • 确保仅暴露你想要的类/方法。
  • 使你在查看URL时,能有一个很好的猜测,知道应该调用哪个类/方法。

这就是全部。以下是一个路由器操作的示例

# do a little setup. 
$router = new Lucid\Router\Router();
$router->setViewClassPrefixSuffix("App\View\", ''); # note: this is the default
$router->setControllerClassPrefixSuffix("App\Controller\", ''); # note: this is the default
$router->allowObjects('*');
$router->allowViewMethods('*', 'viewOne', 'viewList');
$router->allowControllerMethods('*', 'saveChanges', 'deleteOne');

$route1 = $router->parseRoute('/Users/viewOne/3');
error_log($route1->class.'->'.$route1->method);
 # This should write this to the error log: App\View\Users->viewOne

$route2 = $router->parseRoute('/Users/viewList');
error_log($route2->class.'->'.$route2->method);
 # This should write this to the error log: App\View\Users->viewList

$route3 = $router->parseRoute('/Users/saveChanges/3');
error_log($route3->class.'()->'.$route3->method);
 # This should write this to the error log: App\Controller\Users->saveChanges


$route4 = $router->parseRoute('/Users/methodNotFound');
 # this should throw a Lucid\Router\Exception\MethodNotFound exception

->parseRoute的返回值是一个Lucid\Router\Route的实例,该实例有三个公共属性

  • ->class: 包含路由的完全限定类名的字符串
  • ->method: 包含路由类的方法名的字符串
  • ->parameters: 路由中额外的参数的关联数组。这些参数的名称是可以配置的。默认情况下,第一个额外参数存储在名为'id'的索引中,第二个参数名为'name',之后的索引则命名为'parameter#',其中'#'是参数在URL中的序号位置,从0开始。所以,/Users/viewOne/34/joe/blow会生成如下路由
Lucid\Router\Route Object
(
    [class] => Users
    [method] => viewOne
    [parameters] => Array
        (
            [id] => 34
            [name] => joe
            [parameter2] => blow
        )

)

注意,Lucid\Router\Route的实例有一个公共方法->execute(...$constructParameters),它将尝试实例化类并使用URL中的参数调用该方法,但对于大多数情况来说这可能并不有用。你最好将依赖注入容器与Route对象粘合在一起,这样你的视图/控制器类就可以通过__construct参数指定它们的依赖项。

配置

允许对象/方法

你很可能需要设置以下三个主要配置来使用此路由器,并且所有三个都可以设置为允许任何内容。所有三个都是通过setter方法设置的

  • 允许通过路由的类。通过调用->allowObjects(...string $names)来设置。如果你调用此方法并传递'*'作为值,则路由器将允许任何类名
  • 允许通过路由的视图方法。通过调用->allowViewMethods(string $objectName, ...$methodNames)来设置。
  • 允许通过路由的控制器方法。通过调用->allowControllerMethods(string $objectName, ...$methodNames)来设置。

以下是一个详细示例,展示了如何在相当受限的配置中使用这三个方法

# First, instantiate the router
$router = new Lucid\Router\Router();

# Allow classes with a final name 'Users' or 'Products'.
# Anything else will throw a ForbiddenObject exception
$router->allowObjects('Users', 'Products');

# For the Users view class, only allow methods 'viewOne', and 'changePassword'
# Accessing any other method will throw a ForbiddenMethod exception
$router->allowViewMethods('Users', 'viewOne', 'changePassword);

# For the Users controller class, only allow methods 'save', and 'delete'
# Accessing any other method will throw a ForbiddenMethod exception
$router->allowControllerMethods('Users', 'save', 'delete);

# For the Products view class, only allow methods 'viewOne' and 'viewSimilar'
# Accessing any other method will throw a ForbiddenMethod exception
$router->allowViewMethods('Products', 'viewOne', 'viewSimilar');

# For the Products controller class, only allow methods 'save', and 'addToCart'
# Accessing any other method will throw a ForbiddenMethod exception
$router->allowControllerMethods('Products', 'save', 'addToCart);

配置命名空间

默认情况下,视图的类名以'App\View'前缀,控制器以'App\Controller'前缀来完全限定。你可以通过调用两个setter方法来更改这些默认值

  • ->setViewClassPrefixSuffix(string $prefix = '', string $suffix = '');
  • ->setControllerClassPrefixSuffix(string $prefix = '', string $suffix = '');

以下是一个使用这些方法的示例

# first, instantiate the router
$router = new Lucid\Router\Router();
$router->allowObjects('*');
$router->allowViewMethods('*', 'viewOne', 'viewList');

# Let's see the default fully qualified name first:
$route = $router->parseRoute('/Users/viewOne');
echo($route->class);
# this should echo: App\View\User

# now let's change the configuration to customize the namespace for views:
$router->setViewClassPrefixSuffix("MyApp\MyViews\");
$route = $router->parseRoute('/Users/viewOne');
echo($route->class);
# this should echo: MyApp\MyViews\User

配置控制器命名空间的方式类似

# first, instantiate the router
$router = new Lucid\Router\Router();
$router->allowObjects('*');
$router->allowControllerMethods('*', 'saveChanges', 'deleteOne');

# Let's see the default fully qualified name first:
$route = $router->parseRoute('/Users/saveChanges');
echo($route->class);
# this should echo: App\Controller\User

# now let's change the configuration to customize the namespace for controllers:
$router->setControllerClassPrefixSuffix("MyApp\MyControllers\");
$route = $router->parseRoute('/Users/saveChanges');
echo($route->class);
# this should echo: MyApp\ MyControllers\User

配置参数名称

在默认配置中,前两个参数名为'id'和'name',之后的参数简单地存储为parameter#,其中'#'是参数在路由中的序号索引,从0开始。所以,给定一个如/User/viewOne/34/joe/blow的路由,路由对象将类似于以下内容

Lucid\Router\Route Object
(
    [class] => Users
    [method] => viewOne
    [parameters] => Array
        (
            [id] => 34
            [name] => joe
            [parameter2] => blow
        )

)

可以使用->setParameterNames(...$names)函数设置参数的默认名称。例如

$router = new Lucid\Router\Router();
$router->allowObjects('*');
$router->allowViewMethods('*', 'viewOne');
$router->setParameterNames('data_id');
print_r($router->parseRoute('/Users/viewOne/34/joe/blow'));

你应该得到如下输出

Lucid\Router\Route Object
(
    [class] => Users
    [method] => viewOne
    [parameters] => Array
        (
            [data_id] => 34
            [parameter1] => joe
            [parameter2] => blow
        )

)

建议的配置

最大权限

这是一个非常简单的配置,可以使你的项目启动,但后来应该锁定

$router = new Lucid\Router\Router();
$router->allowObjects('*');
$router->allowViewMethods('*', '*');
$router->allowControllerMethods('*', '*');

注意,在此配置中可能会抛出AmbiguousMethod异常。例如,如果您的Users视图类和Users控制器类都实现了名为'doSomething'的方法,那么给定像'/Users/doSomething'这样的URL时,并不清楚应该实例化哪一个。

大多数情况下无需配置

以下是我喜欢使用的一种配置,它依赖于您对所有类使用相同的CRUD方法命名

$router = new Lucid\Router\Router();
$router->allowObjects('*');
$router->allowViewMethods('*', 'viewOne', 'viewList');
$router->allowControllerMethods('*', 'save', 'delete');

在此配置中,您可以添加新的类(例如:App\View\Products和App\ControllerProducts),并且路由将自动为它们工作。例如

  • /Products/viewOne将自动允许/映射到App\View\Products->viewOne
  • /Products/viewList将自动允许/映射到App\View\Products->viewList
  • /Products/save将自动允许/映射到App\Controller\Products->save
  • /Products/delete将自动允许/映射到App\Controller\Products->delete

大多数情况下无需配置,但有几点特定要求

这基本上与之前的配置相同,增加了一些特定要求。注意:如果您有针对特定对象的允许方法规则,那么这些规则将始终覆盖'*'定义的规则。

$router = new Lucid\Router\Router();
$router->allowObjects('*', 'Authentication');
$router->allowViewMethods('*', 'viewOne', 'viewList');
$router->allowControllerMethods('*', 'save', 'delete');
$router->allowViewMethods('Authentication', 'loginForm', 'resetPasswordForm');
$router->allowControllerMethods('Authentication', 'processLogin', 'processLogout', 'processPasswordReset');

在此配置中,您可以添加新的类(例如:App\View\Products和App\ControllerProducts),并且路由将自动工作。此外,我们还配置了一个名为Authentication的视图/控制器,并为其配置了一些特定的视图/控制器方法。

有用文件

我在/useful文件夹中也包含了一些有用的文件

  • apache_mod_rewrite.conf:如何配置mod_rewrite以使apache与此类一起工作的示例。
  • php_inbuilt_server.php:如何使用PHP的内置服务器以及重写与此类一起工作的示例

未来功能

以下是我可能在未来添加的一些功能的列表

  • 为每个对象/方法配置参数名称的方式
  • 将路由映射到闭包而不是类/方法
  • 国际化的路由别名(/Products/list和/Produits/list都映射到App\View\Products->list)