简体   繁体   English

使用Zend Framework中的Zend_Controller_Router_Route_Regex在参数中匹配多个URL

[英]Matching Multiple URLs with parameters using Zend_Controller_Router_Route_Regex in Zend Framework

i am developing a Rest Controller with Zend and i am confused with the mapping of urls to the Router. 我正在使用Zend开发一个Rest Controller,我对url到Router的映射感到困惑。

Basically i read about Zend Router and i could not plan my urls in order to satisfy the mentioned routes. 基本上我读了Zend路由器 ,我无法计划我的网址,以满足上述路线。

These are some of my urls that should be mapped to Routers. 这些是我应该映射到路由器的一些网址。

  1. http://localhost/api/v1/tags.xml HTTP://localhost/api/v1/tags.xml

  2. http://localhost/api/v1/tags.xml?abc=true (param: abc=true) http://localhost/api/v1/tags.xml?abc = true (param:abc = true)

  3. http://localhost/api/v1/tags/123456.xml (param: 123456.xml) http://localhost/api/v1/tags/123456.xml (param:123456.xml)

  4. http://localhost/api/v1/tags/123456/pings.xml (params: 123456, pings.xml) http://localhost/api/v1/tags/123456/pings.xml (参数:123456,pings.xml)

  5. http://localhost/api/v1/tags/123456/pings.xml?a=1&b=2 (params: 123456, pings.xml, a=1, b=2) http://localhost/api/v1/tags/123456/pings.xml?a = 1&b = 2 (参数:123456,pings.xml,a = 1,b = 2)

  6. http://localhost/api/v1/tags/123456/pings/count.xml (params: 123456, pings, count.xml) http://localhost/api/v1/tags/123456/pings/count.xml (参数:123456,ping,count.xml)

I am planning such that for the url patterns 1 to 3, "tags" should be the controller and for the url patterns 4 to 6, "pings" should be the controller. 我正在计划,对于网址模式1到3,“标签”应该是控制器,对于网址模式4到6,“ping”应该是控制器。

Now i am unsure about how to configure the routers such that the above scenarios will work. 现在我不确定如何配置路由器,以便上述方案可行。 Note that i cannot change these urls. 请注意,我无法更改这些网址。 I can offer 100 of my reputation score to the good answer. 我可以提供100分的良好答案。

First two URLs can be combined to one router. 前两个URL可以组合到一个路由器。

$r = new Zend_Controller_Router_Route_Regex('api/v1/tags.xml',
                array('controller' => 'tags', 'action' => 'index'));
$router->addRoute('route1', $r);

To differentiate the first two routes, check for the presence of the abc parameter in your tags controller. 要区分前两个路由,请检查标记控制器中是否存在abc参数。 Add the following in your tags controller, index action. 在标记控制器中添加以下内容,索引操作。

if($this->_getParam('abc') == "true")
{
//route 2
} else {
// route 1
}

Similarly, routes 4 and 5 can be combined into one route. 类似地,路线4和5可以组合成一个路线。

I have explained for Route 6. For route 3, you can use the same logic. 我已经解释了Route 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);

The parameters can then accessed like the following in pings controller. 然后可以在ping控制器中访问以下参数。

$this->_getParam('param1') and $this->_getParam('param2')

For Route 5 : 对于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);

The parameters (part of the URL after ?) will not be handled in the Router. 路由器不会处理参数(后面的URL的一部分?)。 By default, they will be passed to your controller. 默认情况下,它们将传递给您的控制器。

To get a specifc parameter value passed in your URL, use the following in your controller. 要获取URL中传递的特定参数值,请在控制器中使用以下命令。

$this->_getParam('a');

The logic is use (.*) in your route and assign them a parameter name and access them in your controller 逻辑是在您的路由中使用(。*)并为它们分配参数名称并在您的控制器中访问它们

Here's a starter for a piece of algorithm that distills the controller, indexed params, and extension from the request, which you could incorporate into an extended version of Zend_Rest_Route::match() : 这是一个算法的启动器,它可以从请求中提取控制器,索引的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;
}

It's hardly tested, and thus not production material of course. 它几乎没有经过测试,因此当然不是生产材料。 But it should get you started. 但它应该让你开始。

What this DOES give you so far is: 到目前为止,这给你的是:
The controller 控制器
The extension 扩展名
The indexed parameters 索引参数

What this DOES NOT give you is: 这不能给你的是:
The action (post, put, delete, etc. The algorithm for this is already in Zend_Rest_Route::match() ) 动作(post,put,delete等)这个算法已经在Zend_Rest_Route::match() )中了
The named parameters ( Zend_Controller_Request_Http takes care of that already) 命名参数( Zend_Controller_Request_Http已经完成了)

EDIT 编辑
I realize this answer might be considered a bit vague so far. 我意识到这个答案到目前为止可能被认为有点模糊。 The point is to merge this algorithm with the match() algorithm of Zend_Rest_Route . 重点是将此算法与Zend_Rest_Routematch()算法合并。 But this above code still needs a lot of attention; 但是上面的代码仍然需要很多关注; you want to account for modules too probably (as does Zend_Rest_Route ), and maybe even an optional baseUrl (not sure how ZF deals with this internally actually). 你想要考虑模块( Zend_Rest_Route也是如此),甚至可能是一个可选的baseUrl(不确定ZF如何在内部处理这个问题)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM