-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
226 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
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`` in an ``AcmeDemoBundle``. It is | ||
assumed you already have and 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 list view | ||
- add the route and the new action in the Admin class | ||
|
||
Extending the Admin Controller | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
First we need to create or own Controller extending the one from SonataAdmin | ||
|
||
|
||
.. code-block:: php | ||
<?php // src/Acme/DemoBundle/Controller/CRUDController.php | ||
namespace Acme\DemoBundle\Controller; | ||
use Sonata\AdminBundle\Controller\CRUDController as Controller; | ||
class CRUDController extends Controller | ||
{ | ||
// ... | ||
} | ||
Admin classes by default use ``SonataAdmin:CRUD`` controller , this is the third parameter | ||
of an admin service defintion, we need to change it to our own. | ||
|
||
Either by using XML: | ||
|
||
.. code-block:: xml | ||
<!-- src/Acme/DemoBundle/Resources/config/admin.xml --> | ||
... | ||
<service id="acme.demo.admin.car" class="Acme\DemoBundle\Admin\CarAdmin"> | ||
<tag name="sonata.admin" manager_type="orm" group="Demo" label="Car" /> | ||
<argument /> | ||
<argument>Acme\DemoBundle\Entity\Car</argument> | ||
<argument>AcmeDemoBundle:CRUD</argument | ||
... | ||
</service> | ||
... | ||
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 | ||
|
||
TODO: link | ||
|
||
|
||
Create the custom action in our Controller | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Now it's time to actually create your custom action here, for this example i chose | ||
to implement a ``clone`` action. | ||
|
||
.. code-block:: php | ||
<?php // src/Acme/DemoBundle/Controller/CRUDController.php | ||
namespace Acme\DemoBundle\Controller; | ||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | ||
use Sonata\AdminBundle\Controller\CRUDController as Controller; | ||
use Symfony\Component\HttpFoundation\RedirectResponse; | ||
class CRUDController extends Controller | ||
{ | ||
public function cloneAction() | ||
{ | ||
$id = $this->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; | ||
$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 new object. Finally we set a flash message indicating success and redirect to the list view. | ||
|
||
TODO: talk about other options or just refer to https://github.com/sonata-project/SonataAdminBundle/blob/master/Controller/CRUDController.php for reference? | ||
|
||
Create a template for the new action | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
|
||
We need to tell SonataAdmin how to render our new action we do that by creating a ``list__action_clone.html.twig`` in the | ||
namespace of our custom Admin Controller. | ||
|
||
|
||
.. code-block:: twig | ||
{# src/Acme/DemoBundle/Resources/views/CRUD/list__action_clone.html.twig #} | ||
<a href="{{ admin.generateObjectUrl('clone', object) }}">clone</a> | ||
Right now ``clone`` is not a known route, we define it in the next step. | ||
|
||
|
||
Bringing it all together | ||
^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
|
||
What's left now is actually adding our custom action to the admin class | ||
|
||
We have to add the new route in ``configureRoutes`` | ||
|
||
.. code-block:: php | ||
protected function configureRoutes(RouteCollection $collection) | ||
{ | ||
$collection->add('clone', $this->getRouterIdParameter().'/clone'); | ||
} | ||
Which gives us a route like ``../admin/sonata/demo/car/1/clone``. | ||
You could also just do ``$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 example ``CarAdmin.php`` looks like this: | ||
|
||
.. code-block:: php | ||
<?php // src/Acme/DemoBundle/Admin/CarAdmin.php | ||
namespace Acme\DemoBundle\Admin; | ||
// ... | ||
use Sonata\AdminBundle\Route\RouteCollection; | ||
class CarAdmin extends Admin | ||
{ | ||
// ... | ||
protected function configureListFields(ListMapper $listMapper) | ||
{ | ||
$listMapper | ||
->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'); | ||
} | ||
} | ||
Final result looks like this: | ||
|
||
TODO: screenshot | ||
|
||
An example of this for ``CarAdmin`` in the AcmeDemoBundle of sonata-sandbox can be found here: | ||
https://github.com/koyaan/sandbox/commit/5bdbc3528ec095f697a9deec32a4bc8ca8d13321 |