Symfony嵌套资源路由不传递id

时间:2016-02-12 15:04:29

标签: php symfony

这是我的问题的要点。我正在Symfony2中创建一个API,我似乎无法使嵌套路由起作用。

此作品

api_v1_role_show:
    pattern:        /api/v1/roles/{roleId}
    defaults:       { _controller: rest_v1_roles_controller:showAction }
    methods:        [GET]

我可以通过做这样的事来证明它的工作原理

function showAction()
{
  var_dump(func_get_args()); // array(1)
}

这不起作用

api_v1_permission_post:
    pattern:        /api/v1/roles/{roleId}/permissions
    defaults:       { _controller: rest_v1_role_permissions_controller:createAction }
    methods:        [POST]

我最终得到这样的东西:

function createAction()
{
  //This should be array(1)
  var_dump(func_get_args()); // array()
}

我错过了什么?我已经尝试在网上看了一个多小时,我似乎无法找到关于这个主题的任何内容。我不得不怀疑它是否是一个后期安全事件。

REST类结构

我们的申请中有很多休息终点。我们创建了一个休息类,允许我们快速添加名为RestBaseController的新端点,它看起来像这样:

class RestBaseController {

  protected $urlParams;

  public function showAction()
  {
     $this->urlParams = func_get_args();
     //Shows the resource based on ID now stored in $this->urlParams;
  }

  public function createAction()
  {
    $this->urlParams = func_get_args();

    $this->adjustParameters();
    //creates the resource from JSON body, essentially
  }

  protected function adjustParameters()
  {
    return null;
  }
}

然后是我遇到问题的班级:

class RolePermissionsController extends RestBaseController
{
  protected function adjustParameters()
  {
    $role = $this->em()->getRepository('AppBundle:Role')
      ->find($this->urlParams[0]); //This will give me an error saying offset 0 does not exist.
    $this->roleId = $role->getRoleId();
  }
}

我的问题: 如何在Symfony中使用嵌套URL?

2 个答案:

答案 0 :(得分:1)

如果我没有弄错的话,symfony将路径用于反射和"命名参数"。

例如:route:/ api / v1 / roles / {roleId} / permissions / {otherId}

public fucntion action($otherId, $roleId) // position here is not important, important name

你也可以:

public fucntion action(Request $request, $otherId, $roleId)

并且第一个参数将是$ request。

那么伙计,改变你的架构,直到它为时不晚

答案 1 :(得分:0)

In the end, I found two ways to fix this issue. Dmitry pointed out that symfony uses Reflection and "named parameters" to break down the routes into passable arguments that are similar to button.forceTapElement() which means that I would have been able to something like this in

PHP 5.6+

RestBaseController.php

function(Request $request, [ ...$uriExtractedName1, $uriExtractedName2])

But I'm currently working on a project in an earlier version so I had to something a little more simplistic.

PHP 5.4

routing.yml

public function createAction(Request $request, ...$args)
{
  $this->request = $request;
  $this->urlParams = $args;
  //...
}

RestBaseController.php

api_v1_permission_post:
    pattern:        /api/v1/roles/{parentId}/permissions
    defaults:       { _controller: rest_v1_role_permissions_controller:createAction }
    methods:        [POST]

This solution has worked out quite elegantly. I don't like having to always call the parent id public function createAction($parentId = null) { $this->parentId = $parentId; //... } but it's a small price to pay for having exceptionally small controller classes. I realized that the other routers always worked because we call the passed id parentId.