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'); } }