routing.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. Routing
  2. =======
  3. The default routes used in the CRUD controller are accessible through the
  4. ``Admin`` class.
  5. The ``Admin`` class contains two routing methods:
  6. * ``getRoutes()``: Returns the available routes;
  7. * ``generateUrl($name, $options)``: Generates the related routes.
  8. Routing Definition
  9. ------------------
  10. Route names
  11. ^^^^^^^^^^^
  12. You can set a ``baseRouteName`` property inside your ``Admin`` class. This
  13. represents the route prefix, to which an underscore and the action name will
  14. be added to generate the actual route names.
  15. .. note::
  16. This is the internal *name* given to a route (it has nothing to do with the route's visible *URL*).
  17. .. code-block:: php
  18. <?php
  19. // src/AppBundle/Admin/PostAdmin.php
  20. class PostAdmin extends AbstractAdmin
  21. {
  22. protected $baseRouteName = 'sonata_post';
  23. // will result in routes named:
  24. // sonata_post_list
  25. // sonata_post_create
  26. // etc..
  27. // ...
  28. }
  29. If no ``baseRouteName`` is defined then the Admin will generate one for you,
  30. based on the following format: 'admin_vendor_bundlename_entityname' so you will have
  31. route names for your actions like 'admin_vendor_bundlename_entityname_list'.
  32. If the Admin fails to find a baseRouteName for your Admin class a ``RuntimeException``
  33. will be thrown with a related message.
  34. If the admin class is a child of another admin class the route name will be prefixed by the parent route name, example :
  35. .. code-block:: php
  36. <?php
  37. // The parent admin class
  38. class PostAdmin extends AbstractAdmin
  39. {
  40. protected $baseRouteName = 'sonata_post';
  41. // ...
  42. }
  43. // The child admin class
  44. class CommentAdmin extends AbstractAdmin
  45. {
  46. protected $baseRouteName = 'comment'
  47. // will result in routes named :
  48. // sonata_post_comment_list
  49. // sonata_post_comment_create
  50. // etc..
  51. // ...
  52. }
  53. Route patterns (URLs)
  54. ^^^^^^^^^^^^^^^^^^^^^
  55. You can use ``baseRoutePattern`` to set a custom URL for a given ``Admin`` class.
  56. For example, to use ``http://yourdomain.com/admin/foo`` as the base URL for
  57. the ``FooAdmin`` class (instead of the default of ``http://yourdomain.com/admin/vendor/bundle/foo``)
  58. use the following code:
  59. .. code-block:: php
  60. <?php
  61. // src/AppBundle/Admin/FooAdmin.php
  62. class FooAdmin extends AbstractAdmin
  63. {
  64. protected $baseRoutePattern = 'foo';
  65. }
  66. You will then have route URLs like ``http://yourdomain.com/admin/foo/list`` and
  67. ``http://yourdomain.com/admin/foo/1/edit``
  68. If the admin class is a child of another admin class the route pattern will be prefixed by the parent route pattern, example :
  69. .. code-block:: php
  70. <?php
  71. // The parent admin class
  72. class PostAdmin extends AbstractAdmin
  73. {
  74. protected $baseRoutePattern = 'post';
  75. // ...
  76. }
  77. // The child admin class
  78. class CommentAdmin extends AbstractAdmin
  79. {
  80. protected $baseRoutePattern = 'comment'
  81. // ...
  82. }
  83. For comment you will then have route URLs like ``http://yourdomain.com/admin/post/{postId}/comment/list`` and
  84. ``http://yourdomain.com/admin/post/{postId}/comment/{commentId}/edit``
  85. Routing usage
  86. -------------
  87. Inside a CRUD template, a route for the current ``Admin`` class can be generated via
  88. the admin variable's ``generateUrl()`` command:
  89. .. code-block:: html+jinja
  90. <a href="{{ admin.generateUrl('list') }}">List</a>
  91. <a href="{{ admin.generateUrl('list', params|merge('page': 1)) }}">List</a>
  92. Note that you do not need to provide the Admin's route prefix (``baseRouteName``) to
  93. generate a URL for the current Admin, just the action name.
  94. To generate a URL for a different Admin you just use the Route Name with the usual
  95. Twig helpers:
  96. .. code-block:: html+jinja
  97. <a href="{{ path('admin_app_post_list') }}">Post List</a>
  98. Create a route
  99. --------------
  100. You can register new routes by defining them in your ``Admin`` class. Only Admin
  101. routes should be registered this way.
  102. The routes you define in this way are generated within your Admin's context, and
  103. the only required parameter to ``add()`` is the action name. The second parameter
  104. can be used to define the URL format to append to ``baseRoutePattern``, if not set
  105. explicitly this defaults to the action name.
  106. .. code-block:: php
  107. <?php
  108. // src/AppBundle/Admin/MediaAdmin.php
  109. use Sonata\AdminBundle\Route\RouteCollection;
  110. class MediaAdmin extends AbstractAdmin
  111. {
  112. protected function configureRoutes(RouteCollection $collection)
  113. {
  114. $collection->add('myCustom'); // Action gets added automatically
  115. $collection->add('view', $this->getRouterIdParameter().'/view');
  116. }
  117. }
  118. Make use of all route parameters
  119. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  120. As the ``add`` method create a Symfony ``Route``, you can use all constructor arguments of the ``Route`` as parameters
  121. in the ``add`` method to set additional settings like this:
  122. .. code-block:: php
  123. <?php
  124. // src/AppBundle/Admin/MediaAdmin.php
  125. use Sonata\AdminBundle\Route\RouteCollection;
  126. class MediaAdmin extends AbstractAdmin
  127. {
  128. protected function configureRoutes(RouteCollection $collection)
  129. {
  130. $collection->add('custom_action', $this->getRouterIdParameter().'/custom-action', array(), array(), array(), '', array('https'), array('GET', 'POST'));
  131. }
  132. }
  133. Other steps needed to create your new action
  134. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  135. In addition to defining the route for your new action you also need to create a
  136. handler for it in your Controller. By default Admin classes use ``SonataAdminBundle:CRUD``
  137. as their controller, but this can be changed by altering the third argument when defining
  138. your Admin service (in your admin.yml file).
  139. For example, lets change the Controller for our MediaAdmin class to AppBundle:MediaCRUD:
  140. .. configuration-block::
  141. .. code-block:: yaml
  142. # src/AppBundle/Resources/config/admin.yml
  143. app.admin.media:
  144. class: AppBundle\Admin\MediaAdmin
  145. tags:
  146. - { name: sonata.admin, manager_type: orm, label: "Media" }
  147. arguments:
  148. - ~
  149. - AppBundle\Entity\Page
  150. - 'AppBundle:MediaCRUD' # define the new controller via the third argument
  151. public: true
  152. We now need to create our Controller, the easiest way is to extend the basic Sonata CRUD controller:
  153. .. code-block:: php
  154. <?php
  155. // src/AppBundle/Controller/MediaCRUDController.php
  156. namespace AppBundle\Controller;
  157. use Sonata\AdminBundle\Controller\CRUDController;
  158. class MediaCRUDController extends CRUDController
  159. {
  160. public function myCustomAction()
  161. {
  162. // your code here ...
  163. }
  164. }
  165. Removing a route
  166. ----------------
  167. Extending ``Sonata\AdminBundle\Admin\AbstractAdmin`` will give your Admin classes the following
  168. default routes:
  169. * batch
  170. * create
  171. * delete
  172. * export
  173. * edit
  174. * list
  175. * show
  176. You can view all of the current routes defined for an Admin class by using the console to run
  177. .. code-block:: bash
  178. $ php app/console sonata:admin:explain <<admin.service.name>>
  179. for example if your Admin is called sonata.admin.foo you would run
  180. .. code-block:: bash
  181. $ php app/console sonata:admin:explain app.admin.foo
  182. Sonata internally checks for the existence of a route before linking to it. As a result, removing a
  183. route will prevent links to that action from appearing in the administrative interface. For example,
  184. removing the 'create' route will prevent any links to "Add new" from appearing.
  185. Removing a single route
  186. ^^^^^^^^^^^^^^^^^^^^^^^
  187. Any single registered route can be easily removed by name:
  188. .. code-block:: php
  189. <?php
  190. // src/AppBundle/Admin/MediaAdmin.php
  191. use Sonata\AdminBundle\Route\RouteCollection;
  192. class MediaAdmin extends AbstractAdmin
  193. {
  194. protected function configureRoutes(RouteCollection $collection)
  195. {
  196. $collection->remove('delete');
  197. }
  198. }
  199. Removing all routes except named ones
  200. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  201. If you want to disable all default Sonata routes except few whitelisted ones, you can use
  202. the ``clearExcept()`` method. This method accepts an array of routes you want to keep active.
  203. .. code-block:: php
  204. <?php
  205. // src/AppBundle/Admin/MediaAdmin.php
  206. use Sonata\AdminBundle\Route\RouteCollection;
  207. class MediaAdmin extends AbstractAdmin
  208. {
  209. protected function configureRoutes(RouteCollection $collection)
  210. {
  211. // Only `list` and `edit` route will be active
  212. $collection->clearExcept(array('list', 'edit'));
  213. // You can also pass a single string argument
  214. $collection->clearExcept('list');
  215. }
  216. }
  217. Removing all routes
  218. ^^^^^^^^^^^^^^^^^^^
  219. If you want to remove all default routes, you can use ``clear()`` method.
  220. .. code-block:: php
  221. <?php
  222. // src/AppBundle/Admin/MediaAdmin.php
  223. use Sonata\AdminBundle\Route\RouteCollection;
  224. class MediaAdmin extends AbstractAdmin
  225. {
  226. protected function configureRoutes(RouteCollection $collection)
  227. {
  228. // All routes are removed
  229. $collection->clear();
  230. }
  231. }
  232. Removing routes only when an Admin is embedded
  233. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  234. To prevent some routes from being available when one Admin is embedded inside another one
  235. (e.g. to remove the "add new" option when you embed ``TagAdmin`` within ``PostAdmin``) you
  236. can use ``hasParentFieldDescription()`` to detect this case and remove the routes.
  237. .. code-block:: php
  238. <?php
  239. // src/AppBundle/Admin/TagAdmin.php
  240. use Sonata\AdminBundle\Route\RouteCollection;
  241. class TagAdmin extends AbstractAdmin
  242. {
  243. protected function configureRoutes(RouteCollection $collection)
  244. {
  245. // prevent display of "Add new" when embedding this form
  246. if ($this->hasParentFieldDescription()) {
  247. $collection->remove('create');
  248. }
  249. }
  250. }
  251. Persistent parameters
  252. ---------------------
  253. In some cases, the interface might be required to pass the same parameters
  254. across the different ``Admin``'s actions. Instead of setting them in the
  255. template or doing other weird hacks, you can define a ``getPersistentParameters``
  256. method. This method will be used when a link is being generated.
  257. .. code-block:: php
  258. <?php
  259. // src/AppBundle/Admin/MediaAdmin.php
  260. class MediaAdmin extends AbstractAdmin
  261. {
  262. public function getPersistentParameters()
  263. {
  264. if (!$this->getRequest()) {
  265. return array();
  266. }
  267. return array(
  268. 'provider' => $this->getRequest()->get('provider'),
  269. 'context' => $this->getRequest()->get('context', 'default'),
  270. );
  271. }
  272. }
  273. If you then call ``$admin->generateUrl('create')`` somewhere, the generated URL looks like this: ``/admin/module/create?context=default``
  274. Changing the default route in a List Action
  275. -------------------------------------------
  276. Usually the identifier column of a list action links to the edit screen. To change the
  277. list action's links to point to a different action, set the ``route`` option in your call to
  278. ``ListMapper::addIdentifier()``. For example, to link to show instead of edit:
  279. .. code-block:: php
  280. <?php
  281. // src/AppBundle/Admin/PostAdmin.php
  282. class PostAdmin extends AbstractAdmin
  283. {
  284. public function configureListFields(ListMapper $listMapper)
  285. {
  286. $listMapper
  287. ->addIdentifier('name', null, array(
  288. 'route' => array(
  289. 'name' => 'show'
  290. )
  291. ));
  292. }
  293. }