【问题标题】:Symfony nested resource routing not passing idsSymfony 嵌套资源路由不传递 id
【发布时间】:2016-02-12 15:04:28
【问题描述】:

这是我的问题的要点。我正在 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();
  }
}

我的问题: 如何让嵌套 URL 在 Symfony 中工作?

【问题讨论】:

  • 您不必在路由定义中省略Action 部分吗?例如rest_v1_role_permission_controller:create
  • 我认为我调用它所调用的方法并不重要。我改变了它,看看这是否与它有关,它返回了相同的结果。
  • 您能否澄清一下究竟是什么不起作用?您收到一些错误吗?
  • 当我无法在我的 API 中创建资源时,我得到一个自我强加的 422 错误。但我遇到的问题是roleId 没有传递给createAction
  • 为什么你使用func_get_args()而不是通过像public function createAction($roleId)这样的函数传递路由参数?

标签: php symfony


【解决方案1】:

如果我没记错的话,symfony 路由使用反射和“命名参数”。

例如:路由:/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。

所以伙计,改变你的架构,直到为时不晚

【讨论】:

  • 哈哈,可惜来不及了;有很多原因。我们计划在不久的将来将 API 提取到它自己的服务中,这很好。
  • 所以我确实找到了解决这个问题的方法,感谢您的反射和命名参数评论。
【解决方案2】:

最后,我找到了两种方法来解决这个问题。 Dmitry 指出 symfony 使用反射和“命名参数”将路由分解为类似于function(Request $request, [ ...$uriExtractedName1, $uriExtractedName2]) 的可传递参数,这意味着我可以在

PHP 5.6+

RestBaseController.php

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

但我目前正在处理一个早期版本的项目,所以我不得不做一些更简单的事情。

PHP 5.4

routing.yml

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

RestBaseController.php

public function createAction($parentId = null)
{
  $this->parentId = $parentId;
  //...
}

这个解决方案非常优雅。我不喜欢总是调用父 ID parentId,但对于拥有非常小的控制器类来说这是一个很小的代价。我意识到其他路由器总是工作,因为我们调用传递的 id id

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-05
    相关资源
    最近更新 更多