Advanced configuration ====================== Service Configuration --------------------- When you create a new Admin service you can configure its dependencies, the services which are injected by default are: ========================= ============================================= Dependencies Service Id ========================= ============================================= model_manager sonata.admin.manager.%manager-type% form_contractor sonata.admin.builder.%manager-type%_form show_builder sonata.admin.builder.%manager-type%_show list_builder sonata.admin.builder.%manager-type%_list datagrid_builder sonata.admin.builder.%manager-type%_datagrid translator translator configuration_pool sonata.admin.pool router router validator validator security_handler sonata.admin.security.handler menu_factory knp_menu.factory route_builder sonata.admin.route.path_info | sonata.admin.route.path_info_slashes label_translator_strategy sonata.admin.label.strategy.form_component ========================= ============================================= .. note:: %manager-type% is to be replaced by the manager type (orm, doctrine_mongodb...), and the default route_builder depends on it. You have 2 ways of defining the dependencies inside ``services.xml``: * With a tag attribute, less verbose: .. configuration-block:: .. code-block:: xml AppBundle\Entity\Project .. configuration-block:: .. code-block:: yaml app.admin.project: class: AppBundle\Admin\ProjectAdmin tags: - { name: sonata.admin, manager_type: orm, group: "Project", label: "Project", label_translator_strategy: "sonata.admin.label.strategy.native", route_builder: "sonata.admin.route.path_info" } arguments: - ~ - AppBundle\Entity\Project - ~ public: true * With a method call, more verbose .. configuration-block:: .. code-block:: xml AppBundle\Entity\Project .. configuration-block:: .. code-block:: yaml app.admin.project: class: AppBundle\Admin\ProjectAdmin tags: - { name: sonata.admin, manager_type: orm, group: "Project", label: "Project" } arguments: - ~ - AppBundle\Entity\Project - ~ calls: - [ setLabelTranslatorStrategy, [ "@sonata.admin.label.strategy.native" ]] - [ setRouteBuilder, [ "@sonata.admin.route.path_info" ]] public: true If you want to modify the service that is going to be injected, add the following code to your application's config file: .. configuration-block:: .. code-block:: yaml # app/config/config.yml admins: sonata_admin: sonata.order.admin.order: # id of the admin service this setting is for model_manager: # dependency name, from the table above sonata.order.admin.order.manager # customised service id Creating a custom RouteBuilder ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ To create your own RouteBuilder create the PHP class and register it as a service: * php Route Generator .. code-block:: php add('yourSubAction'); // The create button will disappear, delete functionality will be disabled as well // No more changes needed! $collection->remove('create'); $collection->remove('delete'); } } * xml service registration .. configuration-block:: .. code-block:: xml * YAML service registration .. configuration-block:: .. code-block:: yaml services: app.admin.entity_route_builder: class: AppBundle\Route\EntityRouterBuilder arguments: - "@sonata.admin.audit.manager" Inherited classes ----------------- You can manage inherited classes by injecting subclasses using the service configuration. Lets consider a base class named `Person` and its subclasses `Student` and `Teacher`: .. configuration-block:: .. code-block:: xml AppBundle\Entity\Person AppBundle\Entity\Student AppBundle\Entity\Teacher You will just need to change the way forms are configured in order to take into account these new subclasses: .. code-block:: php getSubject(); $formMapper ->add('name') ; if ($subject instanceof Teacher) { $formMapper->add('course', 'text'); } elseif ($subject instanceof Student) { $formMapper->add('year', 'integer'); } } Tab Menu -------- ACL ^^^ Though the route linked by a menu may be protected the Tab Menu will not automatically check the ACl for you. The link will still appear unless you manually check it using the `hasAccess` method: .. code-block:: php addChild($this->trans('Show'), array('uri' => $admin->generateUrl('show', array('id' => $id)))); // Link will only appear if access to ACL protected URL is granted if ($this->hasAccess('edit')) { $menu->addChild($this->trans('Edit'), array('uri' => $admin->generateUrl('edit', array('id' => $id)))); } } Dropdowns ^^^^^^^^^ You can use dropdowns inside the Tab Menu by default. This can be achieved by using the `'dropdown' => true` attribute: .. code-block:: php addChild('comments', array('attributes' => array('dropdown' => true))); $menu['comments']->addChild('list', array('uri' => $admin->generateUrl('listComment', array('id' => $id)))); $menu['comments']->addChild('create', array('uri' => $admin->generateUrl('addComment', array('id' => $id)))); } If you want to use the Tab Menu in a different way, you can replace the Menu Template: .. configuration-block:: .. code-block:: yaml # app/config/config.yml sonata_admin: templates: tab_menu_template: AppBundle:Admin:own_tab_menu_template.html.twig Translations ^^^^^^^^^^^^ The translation parameters and domain can be customised by using the ``translation_domain`` and ``translation_parameters`` keys of the extra array of data associated with the item, respectively. .. code-block:: php setExtras(array( 'translation_parameters' => array('myparam' => 'myvalue'), 'translation_domain' => 'My domain', )); You can also set the translation domain on the menu root, and children will inherit it : .. code-block:: php setExtra('translation_domain', 'My domain'); Filter parameters ^^^^^^^^^^^^^^^^^ You can add or override filter parameters to the Tab Menu: .. code-block:: php getFilterParameters(); // Add or override filter parameters $filterParameters['status'] = array( 'type' => EqualType::TYPE_IS_EQUAL, // => 1 'value' => Delivery::STATUS_OPEN, ); // Add filters to uri of tab $menu->addChild('List open deliveries', array('uri' => $this->generateUrl('list', array( 'filter' => $filterParameters, )))); return; } } } The `Delivery` class is based on the `sonata_type_translatable_choice` example inside the Core's documentation: http://sonata-project.org/bundles/core/master/doc/reference/form_types.html#sonata-type-translatable-choice Actions Menu ------------ You can add custom items to the actions menu for a specific action by overriding the following method: .. code-block:: php public function configureActionButtons(AdminInterface $admin, $list, $action, $object) { if (in_array($action, array('show', 'edit', 'acl')) && $object) { $list['custom'] = array( 'template' => 'AppBundle:Button:custom_button.html.twig', ); } // Remove history action unset($list['history']); return $list; } .. figure:: ../images/custom_action_buttons.png :align: center :alt: Custom action buttons Disable content stretching -------------------------- You can disable ``html``, ``body`` and ``sidebar`` elements stretching. These containers are forced to be full height by default. If you use custom layout or just don't need such behavior, add ``no-stretch`` class to the ```` tag. For example: .. code-block:: html+jinja {# src/AppBundle/Resources/views/standard_layout.html.twig #} {% block html_attributes %}class="no-js no-stretch"{% endblock %} Custom Action Access Management ------------------------------- You can customize the access system inside the CRUDController by adding some entries inside the `$accessMapping` array in the linked Admin. .. code-block:: php 'EDIT', 'myCustomBar' => array('EDIT', 'LIST'), ); } admin->checkAccess('myCustomFoo'); // If you can't access to EDIT role for the linked admin, an AccessDeniedException will be thrown // ... } public function myCustomBarAction($object) { $this->admin->checkAccess('myCustomBar', $object); // If you can't access to EDIT AND LIST roles for the linked admin, an AccessDeniedException will be thrown // ... } // ... } You can also fully customize how you want to handle your access management by simply overriding ``checkAccess`` function .. code-block:: php customAccessLogic(); } // ... }