Web开发中的router和平时家里拨号上网使用的路由器不是一回事,Web开发中的router会把用户传递过来的URL解析成相应的参数并传递给http程序来解释执行。
在MVC模式中,用户能够访问的是Controller/Action,然后http程序会根据用户访问的Controller/Action把页面呈现给用户,而router就是负责把这个把用户访问的URL解释为Controller/Action的解释器
router是Phalcon中必须被DI依赖注入器注册的部件,因为这是MVC框架运行所必需的,否则无法解析URL
router的基本用法就是:1.定义一个router;2.定义其解析规则;3.将其注册到DI
当然也可以使用更简单的办法,就是在DI注册时使用匿名函数,一次完成所有操作
$di->set('router', function () {
$router = new \Phalcon\Mvc\Router();
$router->add('/:module/:controller/:action/:params', array(
'module' => 1,
'controller' => 2,
'action' => 3,
'params' => 4,
));
return $router;
});
其中最复杂的就是定义解析规则,router会根据用户定义的规则将URL解析到合适的控制器和行为上
最简单的解析规则就是直接给出URL的定义,使用router的add()函数
//Define a route
$router->add(
"/admin/users/my-profile",
array(
"controller" => "users",
"action" => "profile",
)
);
//Another route
$router->add(
"/admin/users/change-password",
array(
"controller" => "users",
"action" => "changePassword",
)
);
//Define a route
$router->add(
"/admin/:controller/a/:action/:params",
array(
"controller" => 1,
"action" => 2,
"params" => 3,
)
);
对于一些特殊的URL还可以使用正则表达式
$router->add(
"/news/([0-9]{4})/([0-9]{2})/([0-9]{2})/:params",
array(
"controller" => "posts",
"action" => "show",
"year" => 1, // ([0-9]{4})
"month" => 2, // ([0-9]{2})
"day" => 3, // ([0-9]{2})
"params" => 4, // :params
)
);
注意识别字段时以1开始,而不是C或者php风格的从0开始
在Controller/showAction中,可以这样接收传递过来的变量
class PostsController extends \Phalcon\Mvc\Controller
{
public function indexAction()
{
}
public function showAction()
{
// Return "year" parameter
$year = $this->dispatcher->getParam("year");
// Return "month" parameter
$month = $this->dispatcher->getParam("month");
// Return "day" parameter
$day = $this->dispatcher->getParam("day");
}
}
通过dispatcher获取了year/month/day,这样这3个变量就得到了解析,还可以通过setVar("var_name", $var_value)的方式输出到视图里
不使用正则表达式,还可以用花括号代指变量,而不必在router里面指定这个变量
$router->add(
"/documentation/{chapter}/{name}.{type:[a-z]+}",
array(
"controller" => "documentation",
"action" => "show"
)
);
然后在Controller里直接读取chapter和name这2个变量
dispatcher->getParam("name");
// Returns "type" parameter
$year = $this->dispatcher->getParam("type");
}
}
还有一种短写语法
// Short form
$router->add("/posts/{year:[0-9]+}/{title:[a-z\-]+}", "Posts::show");
// Array form:
$router->add(
"/posts/([0-9]+)/([a-z\-]+)",
array(
"controller" => "posts",
"action" => "show",
"year" => 1,
"title" => 2,
)
);
$router->add('/news/{country:[a-z]{2}}/([a-z+])/([a-z\-+])',
array(
'section' => 2, //Positions start with 2
'article' => 3
)
);
识别的时候,要注意因为1号位(注意Phalcon识别是从1开始,而不是从0开始)已经被花括号变量名识别过了,所以在后面的对应关系中必须要从2开始
对于多模块的程序,router中必须包含module的信息
$router->add("/login", array(
'module' => 'backend',
'controller' => 'Backend\Controllers\Login',
'action' => 'index',
));
$router->add("/products/:action", array(
'module' => 'frontend',
'controller' => 'products',
'action' => 1,
));
必要时可以使用带命名空间的全名
如果开发者希望在http访问方式不同时,能够产生不同的行为,还可以这样
// This route only will be matched if the HTTP method is GET
$router->addGet("/products/edit/{id}", "Posts::edit");
// This route only will be matched if the HTTP method is POST
$router->addPost("/products/save", "Posts::save");
// This route will be matched if the HTTP method is POST or PUT
$router->add("/products/update")->via(array("POST", "PUT"));
// Taking URI from $_GET["_url"] $router->handle(); // or Setting the URI value directly $router->handle("/employees/edit/17"); // Getting the processed controller echo $router->getControllerName(); // Getting the processed action echo $router->getActionName(); //Get the matched route $route = $router->getMatchedRoute();通过handle()函数,可以解析URL,然而这并不会直接发生什么作用,而是要通过getControllerName()和getActionName()这两个函数才能发挥作用,一般这两个函数用于用户权限判定,以确定用户是否有对应的Controller/Action的访问权限。
另外在用户输入错误的URL时,还可以这样处理
$router->notFound(array(
'module' => 'entrance',
'controller' => 'index',
'action' => 'index',
));
$router->setDefaultModule('entrance');
$router->setDefaultController('index');
$router->setDefaultAction('index');
//These routes simulate real URIs
$testRoutes = array(
'/',
'/index',
'/index/index',
'/index/test',
'/products',
'/products/index/',
'/products/show/101',
);
$router = new Phalcon\Mvc\Router();
//Add here your custom routes
//Testing each route
foreach ($testRoutes as $testRoute) {
//Handle the route
$router->handle($testRoute);
echo 'Testing ', $testRoute, '
';
//Check if some route was matched
if ($router->wasMatched()) {
echo 'Controller: ', $router->getControllerName(), '
';
echo 'Action: ', $router->getActionName(), '
';
} else {
echo 'The route wasn\'t matched by any route
';
}
echo '
';
}
主要就是看看解析的对不对,解析的不对就要调整解析规则
以笔者的经验来看,多module的router解析时比较容易出错,另外param不能为0,在URL中也应该尽量避免0,因为Phalcon会把0的param识别为null,虽然一般来讲数据库相关的网站涉及到id时都是从1开始,一般不会有问题,不过开发者在使用时还是要注意
在官方文档中还有更详尽的内容
https://docs.phalconphp.com/en/latest/reference/routing.html