Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Every parent controller must have `get{SINGULAR}Action($id)` method when i have multi level sub resource in FOS Rest Bundle

I have three controller named BlogController, PostController, CommentController that CommentController is sub resource of PostController and PostController sub resource of BlogController.

/**
 * @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

I define getAction methods, but i get following error:

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

Edit:

I also try to change the method's name to getCommentAction($commentId), getPostAction($postId) and getBlogAction, but it no work.

When I use @RouteResource annotations, method name must be getAction($id), otherwise it doesn't work.

When I change parent of mgh_blog_post_comment router to mgh_blog, it's working!

like image 251
ghanbari Avatar asked Oct 12 '15 18:10

ghanbari


1 Answers

That error description is awful and a big time waster because it doesn't tell you what the real problem is. Try the following:

/**
 * @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)
    {
    ...
    }
}

You didn't have the correct number of arguments in the descendant controller actions. It took me two days of step debugging to figure this out.

The parent route, Blog, looks like:

/blog/{blogUri}

It will match

public function getAction($blogUri)

The child route, Post, looks like:

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

It will not match the code below because it needs two parameters. The same is true for the grandchild--which is looking for three parameters:

public function getAction($postId)

The grandchild route, Comment, looks like:

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

The code keeps track of the ancestors of each controller. The post has 1 ancestor. When building the routes for the post controller, the code looks at the number of parameters on the 'get action'. It take the number of parameters and subtracts the number of ancestors. If the difference is not equal to one, it throws the error.

Conclusion, for each descendant, it needs to include the ID parameters of it ancestors AND its own ID. There should always be one more parameter than there are ancestors.

like image 194
dlporter98 Avatar answered Sep 29 '22 10:09

dlporter98