Relational RESTful controllers routes

Sometimes it's better to place subresource actions in their own controller, especially when you have more than 2 subresource actions.

有时最好在自己控制器中放置子资源Action,尤其是当您有超过2个以上的子资源Action时。

Resource collection(资源集)

In this case, you must first specify resource relations in special rest YML or XML collection:

在本例中,您首先需要在特定的REST风格的YML或XML集中指定资源关系:

1
2
3
4
5
6
7
8
# src/Acme/HelloBundle/Resources/config/users_routes.yml
users:
     type:     rest
     resource: Acme\HelloBundle\Controller\UsersController
comments:
     type:     rest
     parent:   users
     resource: Acme\HelloBundle\Controller\CommentsController

1
2
3
4
5
6
7
8
<!-- src/Acme/HelloBundle/Resources/config/users_routes.xml -->
<?xml version= "1.0"  encoding= "UTF-8"  ?>
<routes xmlns= "http://friendsofsymfony.github.com/schema/rest"
     xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation= "http://friendsofsymfony.github.com/schema/rest https://raw.github.com/FriendsOfSymfony/FOSRestBundle/master/Resources/config/schema/routing/rest_routing-1.0.xsd" >
     < import  id= "users"  type= "rest"  resource= "Acme\HelloBundle\Controller\UsersController"  />
     < import  type= "rest"  parent= "users"  resource= "Acme\HelloBundle\Controller\CommentsController"  />
</routes>

Notice parent: users option in the second case. This option specifies that the comments resourceis child of the users resource.

注意第二部分的 parent: users 选项。该选项指定了comments资源是user资源的子资源。


It is also necessary to add type: rest to the routing.yml file:

在 routing.yml 文件中, type: rest必须要添加:

1
2
3
4
# app/config/routing.yml
acme_hello:
     type: rest
     resource:  "@AcmeHelloBundle/Resources/config/users_routes.yml"


In this case, your UsersController MUST always have a single resource get... action:

在本例中,您的 UsersController 总是需要有单个资源 get...的Action:

1
2
3
4
5
6
7
<?php
class  UsersController  extends  Controller
{
     public  function  getUserAction( $slug )
     {}  // "get_user"   [GET] /users/{slug}
     ...
}

It's used to determine the parent collection name. Controller name itself not used in routes auto-generation process and can be any name you like.

它被用来确定父集合名。控制器名自身并不用于路由自动生成处理,它可以是您希望的任何名字。

Define child resource controller(定义子资源控制器)

CommentsController actions now will looks like:

CommentsController Action现在看上去如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
class  CommentsController  extends  Controller
{
     public  function  postCommentVoteAction( $slug $id )
     {}  // "post_user_comment_vote" [POST] /users/{slug}/comments/{id}/vote
     public  function  getCommentsAction( $slug )
     {}  // "get_user_comments"   [GET] /users/{slug}/comments
     public  function  getCommentAction( $slug $id )
     {}  // "get_user_comment"    [GET] /users/{slug}/comments/{id}
     public  function  deleteCommentAction( $slug $id )
     {}  // "delete_user_comment" [DELETE] /users/{slug}/comments/{id}
     public  function  newCommentsAction( $slug )
     {}  // "new_user_comments"   [GET] /users/{slug}/comments/new
     public  function  editCommentAction( $slug $id )
     {}  // "edit_user_comment"   [GET] /users/{slug}/comments/{id}/edit
     public  function  removeCommentAction( $slug $id )
     {}  // "remove_user_comment" [GET] /users/{slug}/comments/{id}/remove
}

Notice, we got rid of the User part in action names. That is because the RestBundle routing already knows, that CommentsController::... is child resources of UsersController::getUser()resource.

注意,我们摆脱了Action名中的User部分。这是因为RestBundle路由已经知道,CommentsController::...是 UsersController::getUser()资源的子资源。

Include resource collections in application routing(在应用程序路由中包含资源集)

Last step is mapping of your collection routes into the application routing.yml:

最后一步是将您的集合路由映射到应用程序的 routing.yml 文件中:

1
2
3
4
# app/config/routing.yml
users:
     type:     rest
     resource:  "@AcmeHelloBundle/Resources/config/users_routes.yml"

That's all. Note that it's important to use the type: rest param when including your application'srouting file. Without it, rest routes will still work but resource collections will fail. If you get an exception that contains ...routing loader does not support given key: "parent"... then you are most likely missingthe type: rest param in your application level routes include.

一切搞定。注意当包含您应用程序的路由文件时,type: rest参数是很重要的,如果没有它,REST路由仍会工作,但资源集将失败。如果您得到一个...routing loader does not support given key: "parent"... 的异常的话,那么您最有可能在您应用程序级的路由中没有包含type: rest参数。

Routes naming(路由命名)

RestBundle uses REST paths to generate route name. This means, that URL:

RestBundle功能包使用REST风格的路径来生成路由名,这就意味着,URL:

1
[POST] /users/{slug}/comments/{id}/vote

will become the route with the name post_user_comment_vote.

将变成名为post_user_comment_vote的路由。


For further examples, see comments of controllers in the code above.

进一步示例,请参见上面代码中控制器的注释。

Naming collisions(命名冲突)

Sometimes, routes auto-naming will lead to route names collisions, so RestBundle routecollections provides a name_prefix (name-prefix for xml and @NamePrefix for annotations) parameter (you can use name_prefix only in a file loaded by the rest loader.):

有时,路由自动命名会导致路由名冲突,因此RestBundle路由集提供一个name_prefix参数(xml中是name-prefix、注释则是@NamePrefix),您也可以在被REST加载器加载的文件中只使用name_prefix。

1
2
3
4
5
# app/config/routing.yml
users:
     type: rest  # Required  for  `RestYamlLoader` to process imported routes
     prefix: /api
     resource:  "@AcmeHelloBundle/Resources/config/users_routes.yml"


1
2
3
4
5
# src/Acme/HelloBundle/Resources/config/users_routes.yml
comments:
     type:         rest
     resource:      "@AcmeHelloBundle\Controller\CommentsController"
     name_prefix:  api_ # Our precious parameter


With this configuration, route name would become:

根据这个配置,路由名将变为:

1
api_vote_user_comment

Say NO to name collisions!

对名称冲突说不!


本文转自 firehare 51CTO博客,原文链接:http://blog.51cto.com/firehare/1255753,如需转载请自行联系原作者