我正在使用Zend开发一个Rest控制器,我对网址到路由器的映射感到困惑。
基本上我读了Zend Router,我无法计划我的网址以满足上述路线。
这些是我应该映射到路由器的一些网址。
http://localhost/api/v1/tags.xml?abc=true(param:abc = true)
http://localhost/api/v1/tags/123456.xml(参数:123456.xml)
http://localhost/api/v1/tags/123456/pings.xml(参数:123456,pings.xml)
http://localhost/api/v1/tags/123456/pings.xml?a=1&b=2(参数:123456,pings.xml,a = 1,b = 2)
http://localhost/api/v1/tags/123456/pings/count.xml(参数:123456,ping,count.xml)
我计划对于url模式1到3,“tags”应该是控制器,对于url模式4到6,“ping”应该是控制器。
现在我不确定如何配置路由器,以便上述方案可行。 请注意,我无法更改这些网址。我可以提供100分的良好答案。
答案 0 :(得分:6)
前两个网址可以合并为一个路由器。
$r = new Zend_Controller_Router_Route_Regex('api/v1/tags.xml',
array('controller' => 'tags', 'action' => 'index'));
$router->addRoute('route1', $r);
要区分前两个路由,请检查标记控制器中是否存在abc参数。在标记控制器中添加以下内容,索引操作。
if($this->_getParam('abc') == "true")
{
//route 2
} else {
// route 1
}
同样,路线4和5可以组合成一条路线。
我已针对路线6进行了解释。对于路线3,您可以使用相同的逻辑。
$r = new Zend_Controller_Router_Route_Regex('api/v1/tags/(.*)/pings/(.*)',
array('controller' => 'pings', 'action' => 'index'),
array(1 => 'param1',2=>'param2')
);
$router->addRoute('route6', $r);
然后可以在ping控制器中访问参数,如下所示。
$this->_getParam('param1') and $this->_getParam('param2')
路线5:
$r = new Zend_Controller_Router_Route_Regex('api/v1/tags/(.*)/pings.xml',
array('controller' => 'pings', 'action' => 'index'),
array(1 => 'param1')
);
$router->addRoute('route5', $r);
在路由器中不会处理参数(URL之后的部分?)。默认情况下,它们将传递给您的控制器。
要获取URL中传递的特定参数值,请在控制器中使用以下内容。
$this->_getParam('a');
逻辑是在你的路线中使用(。*)并为它们分配一个参数名称并在你的控制器中访问它们
答案 1 :(得分:4)
这是一个算法的启动器,它可以从请求中提取控制器,索引的params和扩展,您可以将其合并到Zend_Rest_Route::match()
的扩展版本中:
public function match( $request )
{
$path = $request->getPathInfo();
// distill extension (if any) and the remaining path
preg_match( '~(?U:(?<path>.*))(?:\.(?<extension>[^\.]*))?$~', $path, $matches );
$this->_values[ '_extension' ] = isset( $matches[ 'extension' ] ) ? $matches[ 'extension' ] : null;
$path = isset( $matches[ 'path' ] ) ? $matches[ 'path' ] : '';
// split the path into segments
$pathSegments = preg_split( '~' . self::URI_DELIMITER . '~', $path, -1, PREG_SPLIT_NO_EMPTY );
// leave if no path segments found? up to you to decide, but I put it in anyway
if( 0 == ( $length = count( $pathSegments ) ) )
{
return false;
}
// initialize some vars
$params = array();
$controller = null;
// start finding the controller
// (presumes controller found at segment 0, 2, 4, etc...)
for( $i = 0; $i < $length; $i += 2 )
{
// you should probably check here if this is a valid REST controller
// (see Zend_Rest_Route::_checkRestfulController() )
$controller = $params[] = $pathSegments[ $i ];
if( isset( $pathSegments[ $i + 1 ] ) )
{
$params[] = $pathSegments[ $i + 1 ];
}
}
// remove the param which is the actual controller
array_splice( $params, $i - 2, 1 );
// set the controller
$this->_values[ 'controller' ] = $controller;
// merge the params and defaults
$this->_values = array_merge( $this->_values, $params, $this->_defaults );
return $this->_values;
}
它几乎没有经过测试,因此当然不是生产材料。但它应该让你开始。
到目前为止,这给你的是:
控制器
延期
索引参数
这不能给你的是:
动作(发布,放置,删除等。此算法已在Zend_Rest_Route::match()
)中
命名参数(Zend_Controller_Request_Http
已经处理好了)
修改强>
我意识到这个答案到目前为止可能被认为有点模糊。重点是将此算法与match()
Zend_Rest_Route
算法合并。但是上面的代码仍然需要很多关注;你想要考虑模块(和Zend_Rest_Route
一样),甚至可能是一个可选的baseUrl(不确定ZF如何在内部处理它)。