【问题标题】:Every parent controller must have `get{SINGULAR}Action($id)` method when i have multi level sub resource in FOS Rest Bundle当我在 FOS Rest Bundle 中有多级子资源时,每个父控制器都必须有 `get{SINGULAR}Action($id)` 方法
【发布时间】:2015-10-12 18:16:47
【问题描述】:

我有三个控制器,分别命名为BlogControllerPostControllerCommentControllerCommentControllerPostController 的子资源,PostControllerBlogController 的子资源。

/**
 * @Rest\RouteResource("blog", pluralize=false)
 */
class BlogController extends FOSRestController
{
    public function getAction($blogUri)
    {
    ...
    }
}

/**
 * @Rest\RouteResource("post", pluralize=false)
 */
class PostController extends FOSRestController
{
    public function getAction($postId)
    {
    ...
    }
}

/**
 * @Rest\RouteResource("comment", pluralize=false)
 */
class CommentController extends FOSRestController
{
    public function getAction($commentId)
    {
    ...
    }
}

routing.yml

mgh_blog:
    resource: MGH\BlogBundle\Controller\BlogController
    type:     rest

mgh_blog_post:
    resource: MGH\BlogBundle\Controller\PostController
    type:     rest
    parent:   mgh_blog

mgh_blog_post_comment:
    resource: MGH\PostBundle\Controller\CommentController
    type:     rest
    parent:   mgh_blog_post

我定义了getAction 方法,但出现以下错误:

[InvalidArgumentException]                                           
  Every parent controller must have `get{SINGULAR}Action($id)` method  
  where {SINGULAR} is a singular form of associated object 

编辑:

我也尝试将方法名称更改为getCommentAction($commentId)getPostAction($postId)getBlogAction,但没有用。

当我使用@RouteResource注解时,方法名必须是getAction($id),否则不起作用。

当我将 mgh_blog_post_comment 路由器的父级更改为 mgh_blog 时,它正在工作!

【问题讨论】:

  • 能否请您发布命令app/console debug:router的输出?
  • @giosh94mhz debug:router dump InvalidArgumentException 错误
  • 这与您在网络服务器上遇到的错误相同。您需要注释掉有问题的路线,然后运行该命令。这样,我可以看到哪条路线可能会干扰(如果有的话)

标签: symfony fosrestbundle symfony-2.7


【解决方案1】:

那个错误描述很糟糕而且浪费了很多时间,因为它没有告诉你真正的问题是什么。请尝试以下操作:

/**
 * @Rest\RouteResource("blog", pluralize=false)
 */
class BlogController extends FOSRestController
{
    public function getAction($blogUri)
    {
    ...
    }
}

/**
 * @Rest\RouteResource("post", pluralize=false)
 */
class PostController extends FOSRestController
{
    public function getAction($blogUri, $postId)
    {
    ...
    }
}

/**
 * @Rest\RouteResource("comment", pluralize=false)
 */
class CommentController extends FOSRestController
{
    public function getAction($blogUri, $postId, $commentId)
    {
    ...
    }
}

您在后代控制器操作中没有正确数量的参数。我花了两天的时间调试才弄明白。

父路由 Blog 如下所示:

/blog/{blogUri}

会匹配

public function getAction($blogUri)

子路由 Post 如下所示:

/blog/{blogUri}/post/{postId}

它将匹配下面的代码,因为它需要两个参数。孙子也是如此——它正在寻找三个参数:

public function getAction($postId)

孙子路线,评论,看起来像:

/blog/{blogUri}/post/{postId}/comment/{commentId}

代码跟踪每个控制器的祖先。 帖子有 1 个祖先。在为 post 控制器构建路由时,代码会查看“获取操作”上的参数数量。它接受参数的数量并减去祖先的数量。如果差值不等于 1,则会引发错误。

结论,对于每一个后代,都需要包含其祖先的ID参数和自己的ID。应该总是比祖先多一个参数。

【讨论】:

  • 我知道你的感受。我花了 2 天时间梳理代码后才弄明白。我打算写一个更好的错误描述并做一个拉取请求。
【解决方案2】:

你试过了吗?:

class CommentController extends FOSRestController
{
    public function getCommentAction($commentId)
    {
    ...
    }
}

【讨论】:

  • 问题在于后代控制器的单数 get 操作中的参数数量。详情见我的回答。
【解决方案3】:

试试:

public function cgetAction(Request $request)
{
    ...
}

这是我的控制器示例:

<?php

namespace Cf\SClinicBundle\Controller;

use Symfony\Component\HttpFoundation\Request;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\RouteResource;
use Cf\SClinicBundle\Entity\CfAcquireImage;
use Doctrine\DBAL\DBALException as DBALException;
use Doctrine\ORM\NoResultException as NoResultException;

/**
 * CfAcquireImage controller.
 *
 * @RouteResource("acquire-image")
 */
class ApiCfAcquireImageController extends FOSRestController
{
    /**
     * @var array
     */
    public $status;

    /**
     * @var
     */
    public $parameter;

    /**
     * @var
     */
    private $role_name;

    /**
     * Constructor
     */
    public function __construct()
    {

    }

    /**
     * Lists all Cf Acquire Image entities.
     *
     * @param Request $request
     *
     * @return mixed
     */
    public function cgetAction(Request $request)
    {

    }

    /**
     * Finds a Cf Acquire Image entity by id.
     *
     * @param Request $request
     * @param         $id $id
     *
     * @return array
     */
    public function getAction(Request $request, $id)
    {

    }

    /**
     * Create a new Cf Acquire Image entity.
     *
     * @param Request $request
     *
     * @return mixed
     */
    public function postAction(Request $request)
    {

    }

    /**
     * @param Request $request
     * @param         $id
     *
     * @return array
     */
    public function putAction(Request $request, $id)
    {

    }

    /**
     * Deletes a Cf Acquire Image entity.
     *
     * @param Request $request
     * @param         $id
     *
     * @return mixed
     */
    public function deleteAction(Request $request, $id)
    {

    }
}

【讨论】:

  • 我有cgetAction方法,这个问题不是我所说的cgetAction,需要get{SINGULAR}Action($id)方法
  • 单数只有:public function getAction(Request $request, $id) { }
  • 感谢帮助,我定义了这个方法,我认为fos不能处理多级子资源
  • @ghanbari 它可以处理多级祖先。问题是争论的数量。详情见我的回答。
猜你喜欢
  • 2017-08-28
  • 2016-01-04
  • 2015-12-09
  • 1970-01-01
  • 2012-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多