dev-lucid / router
一个简单的路由解析库。
Requires
- php: ^7.0
Requires (Dev)
- phpunit/phpunit: ^5.0
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)