Zend Framework - 路由
路由将请求 URI映射到特定控制器的方法。在本章中,我们将了解如何在 Zend Framework 中实现路由。
一般来说,任何 URI 都有三个部分 −
- 主机名段,
- 路径段,和
- 查询段。
例如,在 URI / URL − http://www.example.com/index?q=data 中,www.example.com 是主机名段,index 是路径段,q=data 是查询段。通常,路由会根据一组约束检查页面段。如果任何约束匹配,则返回一组值。其中一个主要值是控制器。
在特定情况下,路由还会检查主机段、查询段、请求 HTTP 方法、请求 HTTP 标头等。
Route & RouteStack
路由是路由中的主要对象。Zend Framework 为路由对象提供了一个特殊的接口 RouteInterface。所有路由对象都需要实现 RouteInterface。RouteInterface 的完整列表如下 −
namespace Zend\Mvc\Router; use Zend\Stdlib\RequestInterface as Request; interface RouteInterface { public static function factory(array $options = []); public function match(Request $request); public function assemble(array $params = [], array $options = []); }
主要方法是 match。此 match 方法根据其中定义的约束检查给定的请求。如果找到任何匹配项,它将返回 RouteMatch 对象。此 RouteMatch 对象将匹配请求的详细信息作为参数提供。可以使用 getParams 方法从 RouteObject 中提取这些参数。
RouteObject 的完整列表如下 −
namespace Zend\Mvc\Router; class RouteMatch { public function __construct(array $params); public function setMatchedRouteName($name); public function getMatchedRouteName(); public function setParam($name, $value); public function getParams(); public function getParam($name, $default = null); }
一般来说,典型的 MVC 应用程序有许多路由。每个路由将按 LIFO 顺序进行处理,并匹配和返回单个路由。如果没有路由匹配/返回,则应用程序返回"页面未找到"错误。Zend Framework 提供了一个接口来处理路由,RouteStackInterface。此 RouteStackInterface 具有添加/删除路由的选项。
RouteStackInterface 的完整列表如下 −
namespace Zend\Mvc\Router; interface RouteStackInterface extends RouteInterface { public function addRoute($name, $route, $priority = null); public function addRoutes(array $routes); public function removeRoute($name); public function setRoutes(array $routes); }
Zend 框架提供了 RouteStack 接口的两种实现,如下所示 −
- SimpleRouteStack
- TreeRouteStack
路由类型
Zend 框架为"Zend\Mvc\Router\Http"命名空间下的所有情况提供了大量现成的路由对象。选择并使用适合特定情况的路由对象就足够了。
可用的路由如下 −
Hostname − 用于匹配 URI 的主机部分。
Literal − 用于匹配精确 URI。
Method −用于匹配传入请求的 HTTP 方法。
Part − 用于使用自定义逻辑匹配 URI 路径段的一部分。
Regex − 用于通过 Regex Pattern 匹配 URI 路径段。
Schema − 用于匹配 URI Schema,例如 http、https 等。
Segment − 用于通过将 URI 路径拆分为多个段来匹配 URI 路径。
让我们看看如何编写最常用的文字和段路由。路由通常在每个模块的配置文件中指定 - module.config.php。
文字路由
通常,路由按 LIFO 顺序查询。文字路由用于对 URI 路径进行精确匹配。
其定义如下所示 −
$route = Literal::factory(array( 'route' => '/path', 'defaults' => array('controller' => 'Application\Controller\IndexController', 'action' => 'index',), ));
上述路由与请求 URL 中的 /path 匹配,并返回 index 作为 action 和 IndexController 作为控制器。
分段路由
只要您的 URL 应该包含可变参数,就使用分段路由。
描述如下 −
$route = Segment::factory(array( 'route' => '/:controller[/:action]', 'constraints' => array( 'controller' => '[a-zA-Z][a-zA-Z0-9_-]+', 'action' => '[a-zA-Z][a-zA-Z0-9_-]+', ), 'defaults' => array( 'controller' => 'Application\Controller\IndexController', 'action' => 'index',), ));
此处,段用冒号表示,后跟字母数字字符。如果保留一个段是可选的,则将其括在括号中。每个段可能具有与之关联的约束。每个约束都是一个正则表达式。
在教程模块中配置路由
让我们在教程模块中添加一个段路由。更新教程模块配置文件 - module.config.php,可在 myapp/module/Tutorial/config 中找到。
<?php namespace Tutorial; use Zend\ServiceManager\Factory\InvokableFactory; use Zend\Router\Http\Segment; return [ 'controllers' => [ 'factories' => [ Controller\TutorialController::class => InvokableFactory::class, ], ], 'router' => [ 'routes' => [ 'tutorial' => [ 'type' => Segment::class, 'options' => [ 'route' => '/tutorial[/:action[/:id]]', 'constraints' => [ 'action' => '[a-zA-Z][a-zA-Z0-9_-]*', 'id' => '[0-9]+', ], 'defaults' => [ 'controller' => Controller\TutorialController::class, 'action' => 'index', ], ], ], ], ], 'view_manager' => [ 'template_path_stack' => ['tutorial' => __DIR__ . '/../view',], ], ];
我们已成功为 Tutorial 模块添加了路由。我们距离完成 Tutorial 模块只差一步。我们需要为模块添加 View,我们将在后续章节中学习。