Routing
The default routes used in the CRUD controller are accessible through the
Admin
class.
The Admin
class contains two routing methods:
getRoutes()
: Returns the available routes;generateUrl($name, $options)
: Generates the related routes.
Routing Definition
Route names
You can override the generateBaseRouteName()
method inside your Admin
class.
This represents the route prefix, to which an underscore and the action name will
be added to generate the actual route names:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// src/Admin/PostAdmin.php
final class PostAdmin extends AbstractAdmin
{
protected function generateBaseRouteName(bool $isChildAdmin = false): string
{
return 'sonata_post';
}
// will result in routes named:
// sonata_post_list
// sonata_post_create
// etc..
// ...
}
Note
This is the internal name given to a route (it has nothing to do with the route's visible URL).
By default the Admin will generate the route name for you, based on the following format: 'admin_vendor_bundlename_entityname' so you will have route names for your actions like 'admin_vendor_bundlename_entityname_list'.
If the Admin fails to find a baseRouteName for your Admin class a RuntimeException
will be thrown with a related message.
If the admin class is a child of another admin class the route name will be prefixed by the parent route name, example:
1 2 3 4 5 6 7 8 9 10
// src/Admin/PostAdmin.php
// The parent admin class
final class PostAdmin extends AbstractAdmin
{
protected function generateBaseRouteName(bool $isChildAdmin = false): string
{
return 'sonata_post';
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// src/Admin/CommentAdmin.php
// The child admin class
final class CommentAdmin extends AbstractAdmin
{
protected function generateBaseRouteName(bool $isChildAdmin = false): string
{
return 'comment';
}
// will result in routes named :
// sonata_post_comment_list
// sonata_post_comment_create
// etc..
// ...
}
Route patterns (URLs)
You can override the generateBaseRoutePattern()
method to set a custom URL for a given Admin
class.
For example, to use http://yourdomain.com/admin/foo
as the base URL for
the FooAdmin
class (instead of the default of http://yourdomain.com/admin/vendor/bundle/foo
)
use the following code:
1 2 3 4 5 6 7 8 9
// src/Admin/FooAdmin.php
final class FooAdmin extends AbstractAdmin
{
protected function generateBaseRoutePattern(bool $isChildAdmin = false): string
{
return 'foo';
}
}
You will then have route URLs like http://yourdomain.com/admin/foo/list
and
http://yourdomain.com/admin/foo/1/edit
If the admin class is a child of another admin class the route pattern will be prefixed by the parent route pattern, example:
1 2 3 4 5 6 7 8 9 10 11
// src/Admin/PostAdmin.php
// The parent admin class
final class PostAdmin extends AbstractAdmin
{
protected function generateBaseRoutePattern(bool $isChildAdmin = false): string
{
return 'post';
}
// ...
}
1 2 3 4 5 6 7 8 9 10 11
// src/Admin/CommentAdmin.php
// The child admin class
final class CommentAdmin extends AbstractAdmin
{
protected function generateBaseRoutePattern(bool $isChildAdmin = false): string
{
return 'comment';
}
// ...
}
For comment you will then have route URLs like http://yourdomain.com/admin/post/{postId}/comment/list
and
http://yourdomain.com/admin/post/{postId}/comment/{commentId}/edit
Routing usage
Inside a CRUD template, a route for the current Admin
class can be generated via
the admin variable's generateUrl()
command:
1
<a href="{{ admin.generateUrl('list') }}">List</a>
1
<a href="{{ admin.generateUrl('list', params|merge({'page': 1})) }}">List</a>
Note that you do not need to provide the Admin's route prefix (baseRouteName
) to
generate a URL for the current Admin, only the action name is needed.
To generate a URL to a different Admin, call the Symfony Twig function path
with the Route Name:
1
<a href="{{ path('admin_app_post_list') }}">Post List</a>
Create a route
You can register new routes by defining them in your Admin
class. Only Admin
routes should be registered this way.
The routes you define in this way are generated within your Admin's context, and
the only required parameter to add()
is the action name. The second parameter
can be used to define the URL format to append to baseRoutePattern
, if not set
explicitly this defaults to the action name:
1 2 3 4 5 6 7 8 9 10 11 12
// src/Admin/MediaAdmin.php
use Sonata\AdminBundle\Route\RouteCollectionInterface;
final class MediaAdmin extends AbstractAdmin
{
protected function configureRoutes(RouteCollectionInterface $collection): void
{
$collection->add('myCustom'); // Action gets added automatically
$collection->add('view', $this->getRouterIdParameter().'/view');
}
}
Make use of all route parameters
As the add
method create a Symfony Route
, you can use all constructor arguments of the Route
as parameters
in the add
method to set additional settings like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// src/Admin/MediaAdmin.php
use Sonata\AdminBundle\Route\RouteCollectionInterface;
final class MediaAdmin extends AbstractAdmin
{
protected function configureRoutes(RouteCollectionInterface $collection): void
{
$collection->add(
'custom_action',
$this->getRouterIdParameter().'/custom-action',
[],
[],
[],
'',
['https'],
['GET', 'POST']
);
}
}
Other steps needed to create your new action
In addition to defining the route for your new action you also need to create a
handler for it in your Controller. By default Admin classes use Sonata\AdminBundle\Controller\CRUDController
as their controller, but this can be changed by altering the third argument when defining your Admin service.
For example, lets change the Controller for our MediaAdmin class to App\Controller\MediaCRUDController
:
1 2 3 4 5 6
# config/services.yaml
app.admin.media:
class: App\Admin\MediaAdmin
tags:
- { name: sonata.admin, model_class: App\Entity\Page, controller: App\Controller\MediaCRUDController, manager_type: orm, label: 'Media' }
We now need to create our Controller, the easiest way is to extend the basic Sonata CRUD controller:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// src/Controller/MediaCRUDController.php
namespace App\Controller;
use Sonata\AdminBundle\Controller\CRUDController;
use Symfony\Component\HttpFoundation\Response;
class MediaCRUDController extends CRUDController
{
public function myCustomAction(): Response
{
// your code here ...
}
}
Removing a route
Extending Sonata\AdminBundle\Admin\AbstractAdmin
will give your Admin classes the following
default routes:
- batch
- create
- delete
- export
- edit
- list
- show
You can view all of the current routes defined for an Admin class by using the console to run
1
bin/console sonata:admin:explain <<admin.service.name>>
for example if your Admin is called sonata.admin.foo you would run
1
bin/console sonata:admin:explain app.admin.foo
Sonata internally checks for the existence of a route before linking to it. As a result, removing a route will prevent links to that action from appearing in the administrative interface. For example, removing the 'create' route will prevent any links to "Add new" from appearing.
Removing a single route
Any single registered route can be removed by name:
1 2 3 4 5 6 7 8 9 10 11
// src/Admin/MediaAdmin.php
use Sonata\AdminBundle\Route\RouteCollectionInterface;
final class MediaAdmin extends AbstractAdmin
{
protected function configureRoutes(RouteCollectionInterface $collection): void
{
$collection->remove('delete');
}
}
Removing all routes except named ones
If you want to disable all default Sonata routes except few allowed ones, you can use
the clearExcept()
method. This method accepts an array of routes you want to keep active:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// src/Admin/MediaAdmin.php
use Sonata\AdminBundle\Route\RouteCollectionInterface;
final class MediaAdmin extends AbstractAdmin
{
protected function configureRoutes(RouteCollectionInterface $collection): void
{
// Only `list` and `edit` route will be active
$collection->clearExcept(['list', 'edit']);
// You can also pass a single string argument
$collection->clearExcept('list');
}
}
Removing all routes
If you want to remove all default routes, you can use clear()
method:
1 2 3 4 5 6 7 8 9 10 11 12
// src/Admin/MediaAdmin.php
use Sonata\AdminBundle\Route\RouteCollectionInterface;
final class MediaAdmin extends AbstractAdmin
{
protected function configureRoutes(RouteCollectionInterface $collection): void
{
// All routes are removed
$collection->clear();
}
}
Removing routes only when an Admin is embedded
To prevent some routes from being available when one Admin is embedded inside another one
(e.g. to remove the "add new" option when you embed TagAdmin
within PostAdmin
) you
can use hasParentFieldDescription()
to detect this case and remove the routes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// src/Admin/TagAdmin.php
use Sonata\AdminBundle\Route\RouteCollectionInterface;
final class TagAdmin extends AbstractAdmin
{
protected function configureRoutes(RouteCollectionInterface $collection): void
{
// prevent display of "Add new" when embedding this form
if ($this->hasParentFieldDescription()) {
$collection->remove('create');
}
}
}
Restoring a single route
Any previously removed route can be restored by name:
1 2 3 4 5 6 7 8 9 10 11
// src/Admin/DeletableMediaAdmin.php
use Sonata\AdminBundle\Route\RouteCollectionInterface;
final class DeletableMediaAdmin extends MediaAdmin
{
protected function configureRoutes(RouteCollectionInterface $collection): void
{
$collection->restore('delete');
}
}
Persistent parameters
In some cases, the interface might be required to pass the same parameters
across the different Admin
's actions. Instead of setting them in the
template or doing other weird hacks, you can define a configurePersistentParameters()
method. This method will be used when a link is being generated:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// src/Admin/MediaAdmin.php
final class MediaAdmin extends AbstractAdmin
{
protected function configurePersistentParameters(): array
{
if (!$this->getRequest()) {
return [];
}
return [
'provider' => $this->getRequest()->get('provider'),
'context' => $this->getRequest()->get('context', 'default'),
];
}
}
If you then call $admin->generateUrl('create')
somewhere, the generated
URL looks like this: /admin/module/create?context=default
Changing the default route in a List Action
Usually the identifier column of a list action links to the edit screen. To change the
list action's links to point to a different action, set the route
option in your call to
ListMapper::addIdentifier()
. For example, to link to show instead of edit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// src/Admin/PostAdmin.php
final class PostAdmin extends AbstractAdmin
{
protected function configureListFields(ListMapper $list): void
{
$list
->addIdentifier('name', null, [
'route' => [
'name' => 'show'
]
]);
}
}