【问题标题】:Matching Multiple URLs with parameters using Zend_Controller_Router_Route_Regex in Zend Framework在 Zend Framework 中使用 Zend_Controller_Router_Route_Regex 将多个 URL 与参数匹配
【发布时间】:2011-03-01 09:18:16
【问题描述】:

我正在使用 Zend 开发一个 Rest Controller,但我对 url 到路由器的映射感到困惑。

基本上我读到了Zend Router,但我无法规划我的网址以满足上述路线。

这些是我应该映射到路由器的一些 url。

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

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

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

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

  5. 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(参数:123456,pings,count.xml)

我正在计划,对于 url 模式 1 到 3,“tags”应该是控制器,而对于 url 模式 4 到 6,“pings”应该是控制器。

现在我不确定如何配置路由器以使上述方案正常工作。 请注意,我无法更改这些网址。我可以为好答案提供 100 分的声誉分数。

【问题讨论】:

  • 为什么在所有这些 URL 的开头都有/需要“public/index.php”?
  • 它们不是强制性的,我删除了它们。我只担心将这些 url 路由到它们各自的控制器和操作,传递所需的参数。
  • 尽量保持一致,你的路线就会清晰地出现。 > “tags”应该是控制器,对于 url 模式 4 到 6,“pings”应该是控制器。
  • 我想要的是,对于模式 1 到 3 和 4 到 6,请求应该路由到不同的控制器。在一般情况下,上述所有请求都将路由到“api”控制器(如果模块是默认值),但这会使过程变得忙碌。所以我正在寻找一种将请求路由到不同控制器的方法。我怎样才能做到这一点?

标签: php zend-framework zend-route


【解决方案1】:

前两个 URL 可以组合到一个路由器。

$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);

然后可以在 pings 控制器中访问参数,如下所示。

$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');

逻辑是在你的路由中使用 (.*) 并为它们分配一个参数名称并在你的控制器中访问它们

【讨论】:

  • @emaillenin 谢谢,效果很好,但我无法获得第 5 种情况的正则表达式格式。您可以为此发布一个示例吗?我无法获得参数 a=1&b=2。
  • @dskanth pings.xml 是 URL 的静态部分吗?
  • 抱歉迟到了,但是,pings.xml 是第 5 个 url 的静态部分,我想要之后的部分。
  • 更新了 Route 5 的答案。你的 100 赏金优惠在哪里;)
  • 非常感谢 emaillenin。我对你的答复很满意。我只能在 2 天后为您提供赏金积分,因为您可能知道赏金的过程。
【解决方案2】:

这是一个算法的开始,它从请求中提取控制器、索引参数和扩展,您可以将其合并到 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 已经处理好了)

编辑
我意识到到目前为止,这个答案可能被认为有点模糊。重点是将这个算法与Zend_Rest_Routematch()算法合并。但是上面这段代码还是需要多多注意的;您可能也想考虑模块(Zend_Rest_Route 也是如此),甚至可能是可选的 baseUrl(不确定 ZF 内部实际上是如何处理这个问题的)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-03
    • 1970-01-01
    • 2011-02-04
    • 2020-04-16
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 2011-11-10
    相关资源
    最近更新 更多