【问题标题】:Correct routing for a Rest API with Zend使用 Zend 正确路由 Rest API
【发布时间】:2010-03-01 10:36:53
【问题描述】:

我正在尝试为我的网站实现一个 REST API。

我的问题是默认的 Zend 路由妨碍了。我第一次尝试使用 Zend_Rest_Route 但我无法理解我应该如何将它正确用于“深度”路由,即 website/api/resource1/filter/resource2/id。

使用默认的 Zend 路由,我需要创建一个巨大的 Resource1Controller 来处理所有可能的操作,我认为这不是“好”的方法。

我尝试过使用 Resauce (http://github.com/mikekelly/Resauce/),创建一个 api 模块并添加路由,但我无法让它正常工作:

我添加的模式是:

    $this->addResauceRoutes(array(
        'api/resource' => 'resource',
        'api/resource/:id' => 'custom',
        'api/resource/filter' => 'resource-filter',
        'api/resource/filter/:id' => 'custom',
    ));

这导致了这个:

public function addResauceRoutes($routes) {
    $router = Zend_Controller_Front::getInstance()->getRouter();
    foreach ($routes as $pattern => $controller) {
        $router->addRoute($controller,
            new Zend_Controller_Router_Route($pattern, array(
                'module' => 'api',
                'controller' => $controller
                )
            )
        );
    }
    Zend_Controller_Front::getInstance()->setRouter($router);
  • website/api/resource 让我 Resource1Controller,好的
  • website/api/resource/filter 将我带到 resource1filterController,好的
  • website/api/resource/filter/:id 让我 一个自定义控制器,好的
  • 我希望 website/api/resource/:id 将我带到同一个自定义控制器...但它会将我重定向到 Resource1Controller。

有什么解决方案可以让我正确创建我的 API? Zend_Rest_Route 有什么好的方法吗?


编辑:迈克,

我觉得我不适合使用不同的控制器,因为我需要路径“website/api/resource/:id”和“website/api/resource/filter/:id”来给我几乎准确的相同的结果(唯一的区别是因为过滤器在那里,我可能会在此处收到一条消息,告诉“内容已过滤”)。

当我可以使用相同的控制器并检查是否存在参数“过滤器”时,我认为创建另一个几乎相同的控制器是一种浪费。

但是,我不想使用基本的 Zend 路由,因为对于路径“website/api/resource/filter/resource2”,我希望有一个完全不同的行为,所以我想使用另一个控制器,特别是因为我正在尝试使用 Zend_Rest_Action 并且需要我的控制器使用基本操作 getAction()、putAction()、postAction() 和 deleteAction()。

【问题讨论】:

    标签: zend-framework rest routing


    【解决方案1】:

    请你解释一下为什么你需要两个指向同一个控制器的 URI 模式。更好的解决方案可能是为这两种模式中的每一种都使用一个单独的控制器,并将任何共享逻辑移动到您的模型中。

    为每个路由模式强制使用一个唯一的控制器是一个有意的设计决策,所以我很想听听有关您认为这不合适的用例的更多详细信息。


    我认为这是一种浪费 另一个几乎相同的控制器 当我可以使用相同的 控制器并检查是否有 存在参数“过滤器”。

    就个人而言,我认为将共享逻辑移动到模型中并保持控制器精简更简洁。对我来说,这不是浪费,只是更有条理——随着时间的推移,它会让你的代码更容易管理。

    如果你真的需要使用同一个控制器,你总是可以使用查询参数来代替,这样就可以了:

    api/resource/foo?filter=true
    

    该 URI 将由第一条路由 ('api/resource/:id' => 'custom') 免费处理。

    但请考虑使用两个控制器,我认为这是更好的方法。

    【讨论】:

    • 谢谢迈克。我已经使用了过滤器参数,但是我的一些控制器已经变得非常胖,使用单独的控制器将使我免于使用非常大的 switch 语句。经过深思熟虑后,我想我会像您建议的那样尝试使用多个控制器,因为我认为您谈论随着时间的推移更容易管理的代码是有道理的。非常感谢您的有用建议,我想我想尝试尽可能少地复制代码,但如果我继续那样做,可能最终会让我很难理解。
    【解决方案2】:

    好吧,我没有得到好的控制器的原因是因为 Resauce 使用控制器名称作为路由的名称,它必须是唯一的 - 所以指向“自定义”控制器的第二个 url 无法工作。现在我可以得到我想要的文件了:)

    所以我直接使用 $router->addRoute(); 而不是前面提到的。并每次定义新名称,即使指向同一个控制器。

    例子:

    $router->addRoute('resource', new Zend_Controller_Router_Route('/api/resources/:id', array('module' => 'api', 'controller' => 'resource')));
    $router->addRoute('resourceFiltered', new Zend_Controller_Router_Route('/api/resources/filter1/:id', array('module' => 'api', 'controller' => 'resource', 'filter' => 'filter1'));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-10
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 2011-08-05
      • 2017-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多