objectiveweb / router
轻量级URL路由器
Requires
- php: >=5.4.0
- level-2/dice: ^2.0
Requires (Dev)
- jms/serializer: ~1.1
- phpunit/phpunit: 4.*
README
轻量级URL路由器,支持依赖注入。
安装
将依赖项添加到 composer.json
,然后执行 composer install
{
"require": {
"objectiveweb/router": "~2.0"
}
}
基本用法
在 Objectiveweb 应用程序中,端点指的是响应 URL 路由的 PHP 文件。
底层,route($regex, $callable)
函数将 $regex
与当前请求方法和 URI(例如 "GET endpoint.php/something/([0-9]+)/?") 进行比较,如果匹配,则将捕获的参数传递给 $callable
。
示例端点
<?php
// include the composer autoloader
require_once('../vendor/autoload.php')
use Objectiveweb\Router;
$app = new Router();
// Routes are matched in order
$app->GET('/?', function() {
echo "Hello index';
});
$app->GET('/([a-z]+)/?', function($key) {
switch($key) {
case 'data':
// If the callback returns something, it's sent with status 200 (OK)
// Arrays are automatically encoded to json
return [ 1, 2, 3 ];
break;
default:
throw new \Exception([ 'key' => $key, 'empty' => true ], 404); // respond with custom code
break;
}
});
$app->POST('/panic', function() {
// Exceptions are captured, message is send with the proper code
throw new \Exception('Panic!', 500);
});
// catch all
$app->router("([A_Z]+) (.*), function ($method, $path) {
return "Request matched $method and $path";
});
- GET http://server/endpoint.php 显示
Hello index
- GET http://server/endpoint.php/data 返回包含值 1、2、3 的 json 编码数组
- GET http://server/endpoint.php/test 返回一个在主体中包含 JSON 对象的未找到错误
- POST http://server/endpoint.php/panic 抛出带有 'Panic!' 作为响应的 500 内部服务器错误
控制器
PHP 类可以通过在公开端点(index.php)上使用 controller($path, $class)
绑定到 URL。
$app->controller('/', 'ExampleController');
在这种情况下,请求将映射到相应的类方法,如下所示
<?php
class ExampleController {
// GET /?k=v
function index($querystring) {
}
// GET /(.*)?k=v
function get($path1, $path2, ..., $querystring) {
}
// Runs before all actions
function before() {
}
// Runs before post();
function beforePost($body) {
}
// POST /
function post($body) {
}
// Other request methods are also valid, i.e. head(), options(), beforeHead(), etc
}
如果控制器上存在与第一个参数($path[0])同名的方法,它将使用剩余的参数被调用
// (GET|POST|PUT|...) /example/(.*)
function example($path[1], $path[2], ...) {
// check $_SERVER['REQUEST_METHOD'] and process data
}
此函数名称也可以以请求方法为前缀。在这种情况下,查询参数作为最后一个参数传递
// GET /example/(.*)
function getExample($path[1], $path[2], ..., $_GET) {
}
// POST /example/(.*)
function postExample($path[1], $path[2], ..., $decoded_post_body) {
}
其他请求方法也有效(即 HEAD、OPTIONS 等),请查看示例子目录中的其他用法。
自动路由
您可以使用以下方式在特定命名空间上引导应用程序
$app->run('Namespace');
运行时,路由器自动将传入的请求映射到给定的命名空间。例如,对 /products 的请求将实例化 Namespace\ProductsController
类。
如果控制器不存在,请求将被传递到 Namespace\HomeController
。请查看 example/app-run.php
以获取一个工作演示。
依赖注入
从版本 2.0 开始,路由器扩展了 Dice,它为应用程序提供了一个依赖注入容器。
<?php
// include the composer autoloader
require_once('../vendor/autoload.php')
use Objectiveweb\Router;
$app = new Router();
// Configure the DI container rules for the PDO class
$app->addRule('PDO', [
'shared' => true,
'constructParams' => ['mysql:host=127.0.0.1;dbname=mydb', 'username', 'password']
]);
// From now on, you can get a configured PDO instance using
$pdo = $app->create('PDO');
当绑定到路径时,控制器(以及这些控制器的依赖项)将自动解决。例如,如果您定义了控制器
<?php
namespace MyApplication;
class MyController {
private $pdo;
function __construct(PDO $pdo) {
$this->pdo = pdo;
}
function index() {
// query the database using $this->pdo
}
}
当 MyApplication\MyController
被路由器实例化时,一个配置的 PDO 实例将被注入并按需重用。
您可以通过向控制器的构造函数添加类型提示参数来注入依赖项
function __construct(\Util\Gmaps $gmaps, \DB\ProductsRepository $products) {
$this->gmaps = $gmaps;
$this->products = $products;
}
// Use $this->gmaps and $this->products on other functions
在另一个示例中,让我们实例化 Twig
// index.php
$app = new \Objectiveweb\Router();
$app->addRule('Twig_Loader_Filesystem', array(
'shared' => true,
'constructParams' => [ TEMPLATE_ROOT ]
));
$app->addRule('Twig_Environment', array(
'shared' => true,
'constructParams' => [
[ 'instance' => 'Twig_Loader_Filesystem' ],
[ 'cache' => APP_ROOT.'/cache' ],
[ 'auto_reload' => true ]
],
'call' => [
[ 'addGlobal', [ 'server', $_SERVER['SERVER_NAME'] ] ],
[ 'addGlobal', [ 'app_name', APP_NAME ] ],
[ 'addGlobal', [ 'session', $_SESSION ] ],
[ 'addFunction', [ new Twig_SimpleFunction('url', function ($path) {
return \Objectiveweb\Router::url($path);
})]]
]
));
$app->controller('/', 'MyController')
然后,在控制器构造函数中注入它
class MyController {
private $twig;
private $pdo;
function __construct(Twig_Environment $twig, PDO $pdo) {
$this->twig = $twig;
$this->pdo = $pdo;
}
function index() {
return $this->twig->render(...);
}
}
您也可以使用以下方式获取 twig 引用
$twig = $app->create('Twig_Environment');
规则
Dice 规则可以使用以下属性进行配置
- shared (boolean) - 是否在整个容器中使用单个实例。 查看示例
- inherit (boolean) - 是否将规则也应用于子类(默认为 true)。 查看示例
- constructParams (array) - 传递给构造函数的额外参数。 查看示例
- substitutions (array) - 依赖项的键值替换。 查看示例
- 调用(多维数组)- 在对象构造后将被调用的方法及其参数列表。 查看示例
- instanceOf(字符串)- 要初始化的类名。当未将类名传递给
$app->addRule()
时使用。 查看示例 - shareInstances(数组)- 将在整个单个对象树中共享的类名列表。 查看示例