$route = new Zend_Controller_Router_Route_Regex( 'archive/(\d+)', array( 'controller' => 'archive', 'action' => 'show' ) ); $router->addRoute('archive', $route);
每个定义的regex子模式将被注入到请求对象里。同上述的例子,再成功匹配之后,结果值的数组看起来象这样:
$values = array( 1 => '2006', 'controller' => 'archive', 'action' => 'show' );
Note: 在匹配之前,开头和结尾的斜杠从路由器里的URL中去除掉了。结果,匹配,需要foo/bar这样的regex,而不是/foo/bar。
Note: 行开头和行结尾符号(分别为'^' 和 '$')被自动预先追加到所有表达式。这样,你不需要在你的正则表达式里用它们,你应该匹配整个字符串。
Note: 这个路由类使用#符作为分隔符。这意味着你将需要避免哈希符('#')但不是正斜杠('https://www.jb51.net/')在你的路由定义里。因为'#'符(名称为锚)很少被传给webserver,你将几乎不需要在你的regex里使用它。
你可以用通常的办法获得已定义的子模式的内容:
public function showAction() { $request = $this->getRequest(); $year = $request->getParam(1); // $year = '2006'; }
Note: 注意这个键是整数(1) 而不是字符串('1')。
因为'year'的缺省没有设置,这个路由将和它的标准路由副本不是非常精确地相同。即使我们为'year'声明一个缺省并使子模式可选,也不清楚是否会在拖尾斜杠(trailing slash)上还将有问题。方案是使整个'year'部分和斜杠一起可选但只抓取数字部分:(这段比较绕口,请校对者仔细看看,谢谢 Jason Qi)
$route = new Zend_Controller_Router_Route_Regex( 'archive(?:/(\d+))?', array( 1 => '2006', 'controller' => 'archive', 'action' => 'show' ) ); $router->addRoute('archive', $route);
让我们看看你可能注意到的问题。 给参数使用基于整数的键不是容易管理的办法,今后可能会有问题。这就是为什么有第三个参数。这是个联合数组表示一个regex子模式到参数名键的映射。我们来看看一个简单的例子:
$route = new Zend_Controller_Router_Route_Regex( 'archive/(\d+)', array( 'controller' => 'archive', 'action' => 'show' ), array( 1 => 'year' ) ); $router->addRoute('archive', $route);
这将导致下面的值被注入到请求:
$values = array( 'year' => '2006', 'controller' => 'archive', 'action' => 'show' );
这个映射被任何目录来定义使它能工作于任何环境。键可以包含变量名或子模式索引:
$route = new Zend_Controller_Router_Route_Regex( 'archive/(\d+)', array( ... ), array(1 => 'year') ); // OR $route = new Zend_Controller_Router_Route_Regex( 'archive/(\d+)', array( ... ), array('year' => 1) );
Note: 子模式键必须用整数表示。
注意在请求值中的数字索引不见了,代替的是一个名字变量。当然如果你愿意可以把数字和名字变量混合使用:
$route = new Zend_Controller_Router_Route_Regex( 'archive/(\d+)/page/(\d+)', array( ... ), array('year' => 1) );
这将导致在请求中有混合的值可用。例如:URL将在下列结果中:
$values = array( 'year' => '2006', 2 => 10, 'controller' => 'archive', 'action' => 'show' );
因为regex模型不容易颠倒,如果你想用URL助手或这个类中的 assemble方法,你需要准备一个颠倒的URL。这个颠倒的路径用可由sprintf()解析的字符串来表示并定义为第四个构造参数:
$route = new Zend_Controller_Router_Route_Regex( 'archive/(\d+)', array( ... ), array('year' => 1), 'archive/%s' );
所有这些都已经可能由标准路由对象完成,那么使用Regex路由的好处在哪里?首先,它允许你不受限制地描述任何类型的URL。想象一下你有一个博客并希望创建象这样的URLs,还有把解析它路径元素中的最后部分,01-Using_the_Regex_Router.html,到一个文章的ID和文章的标题/描述;这不可能由标准路由完成。用Regex路由,你可以做象下面的方案:
$route = new Zend_Controller_Router_Route_Regex( 'blog/archive/(\d+)-(.+)\.html', array( 'controller' => 'blog', 'action' => 'view' ), array( 1 => 'id', 2 => 'description' ), 'blog/archive/%d-%s.html' ); $router->addRoute('blogArchive', $route);
正如你所看到的,这个在标准路由上添加了巨大的灵活性。
通过配置文件定义路由规则
例如
[production] routes.archive.route = "archive/:year/*" routes.archive.defaults.controller = archive routes.archive.defaults.action = show routes.archive.defaults.year = 2000 routes.archive.reqs.year = "\d+" routes.news.type = "Zend_Controller_Router_Route_Static" routes.news.route = "news" routes.news.defaults.controller = "news" routes.news.defaults.action = "list" routes.archive.type = "Zend_Controller_Router_Route_Regex" routes.archive.route = "archive/(\d+)" routes.archive.defaults.controller = "archive" routes.archive.defaults.action = "show" routes.archive.map.1 = "year" ; OR: routes.archive.map.year = 1
上述的INI文件可以被读进Zend_Config对象:
$config = new Zend_Config_Ini('/path/to/config.ini', 'production'); $router = new Zend_Controller_Router_Rewrite(); $router->addConfig($config, 'routes');