Creating a Custom Admin Action
==============================
This is a full working example of creating a custom list action for SonataAdmin.
The example is based on an existing ``CarAdmin`` class in an ``AcmeDemoBundle``. It is
assumed you already have an admin service up and running.
The recipe
----------
SonataAdmin provides a very straight-forward way of adding your own custom actions.
To do this we need to:
- extend the ``SonataAdmin:CRUD`` Controller and tell our admin class to use it
- create the custom action in our Controller
- create a template to show the action in the list view
- add the route and the new action in the Admin class
Extending the Admin Controller
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
First you need to create your own Controller extending the one from SonataAdmin
.. code-block:: php
...
Acme\DemoBundle\Entity\Car
AcmeDemoBundle:CRUD
...
...
Or by overwriting the configuration in your ``config.yml``:
.. code-block:: yaml
# app/config/config.yml
services:
acme.demo.admin.car:
class: Acme\DemoBundle\Admin\CarAdmin
tags:
- { name: sonata.admin, manager_type: orm, group: Demo, label: Car }
arguments:
- null
- Acme\DemoBundle\Entity\Car
- AcmeDemoBundle:CRUD
For more information about service configuration please refer to Step 3 of :doc:`../reference/getting_started`
Create the custom action in your Controller
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Now it is time to actually create your custom action here, for this example I chose
to implement a ``clone`` action.
.. code-block:: php
get('request')->get($this->admin->getIdParameter());
$object = $this->admin->getObject($id);
if (!$object) {
throw new NotFoundHttpException(sprintf('unable to find the object with id : %s', $id));
}
$clonedObject = clone $object; // Careful, you may need to overload the __clone method of your object
// to set its id to null
$clonedObject->setName($object->getName()." (Clone)");
$this->admin->create($clonedObject);
$this->addFlash('sonata_flash_success', 'Cloned successfully');
return new RedirectResponse($this->admin->generateUrl('list'));
}
}
Here we first get the id of the object, see if it exists then clone it and insert the clone
as a new object. Finally we set a flash message indicating success and redirect to the list view.
Create a template for the new action
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You need to tell SonataAdmin how to render your new action. You do that by
creating a ``list__action_clone.html.twig`` in the namespace of your custom
Admin Controller.
.. code-block:: html+jinja
{# src/Acme/DemoBundle/Resources/views/CRUD/list__action_clone.html.twig #}
clone
Right now ``clone`` is not a known route, we define it in the next step.
Bringing it all together
^^^^^^^^^^^^^^^^^^^^^^^^
What is left now is actually adding your custom action to the admin class.
You have to add the new route in ``configureRoutes``:
.. code-block:: php
protected function configureRoutes(RouteCollection $collection)
{
$collection->add('clone', $this->getRouterIdParameter().'/clone');
}
This gives us a route like ``../admin/sonata/demo/car/1/clone``.
You could also just write ``$collection->add('clone');`` to get a route like ``../admin/sonata/demo/car/clone?id=1``
Next we have to add the action in ``configureListFields`` specifying the template we created.
.. code-block:: php
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
// other fields...
->add('_action', 'actions', array(
'actions' => array(
'Clone' => array(
'template' => 'AcmeDemoBundle:CRUD:list__action_clone.html.twig'
)
)
))
;
}
The full ``CarAdmin.php`` example looks like this:
.. code-block:: php
addIdentifier('name')
->add('engine')
->add('rescueEngine')
->add('createdAt')
->add('_action', 'actions', array(
'actions' => array(
'Clone' => array(
'template' => 'AcmeDemoBundle:CRUD:list__action_clone.html.twig'
)
)
));
}
protected function configureRoutes(RouteCollection $collection)
{
$collection->add('clone', $this->getRouterIdParameter().'/clone');
}
}