7. Advanced configuration¶
7.1. 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% |
data_source | sonata.admin.data_source.%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 your services config file
(services.xml
or services.yaml
):
7.1.1. With a tag attribute (less verbose)¶
- YAML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# config/services.yaml app.admin.project: class: App\Admin\ProjectAdmin arguments: - ~ - App\Entity\Project - ~ 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'
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
<!-- config/services.xml --> <service id="app.admin.project" class="App\Admin\ProjectAdmin"> <argument/> <argument>App\Entity\Project</argument> <argument/> <tag 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" /> </service>
7.1.2. With a method call (more verbose)¶
- YAML
1 2 3 4 5 6 7 8 9 10 11 12 13
# config/services.yaml app.admin.project: class: App\Admin\ProjectAdmin arguments: - ~ - App\Entity\Project - ~ calls: - [setLabelTranslatorStrategy, ['@sonata.admin.label.strategy.native']] - [setRouteBuilder, ['@sonata.admin.route.path_info']] tags: - { name: sonata.admin, manager_type: orm, group: 'Project', label: 'Project' }
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14
<!-- config/services.xml --> <service id="app.admin.project" class="App\Admin\ProjectAdmin"> <argument/> <argument>App\Entity\Project</argument> <argument/> <call method="setLabelTranslatorStrategy"> <argument type="service" id="sonata.admin.label.strategy.native"/> </call> <call method="setRouteBuilder"> <argument type="service" id="sonata.admin.route.path_info"/> </call> <tag name="sonata.admin" manager_type="orm" group="Project" label="Project"/> </service>
If you want to modify the service that is going to be injected, add the following code to your application’s config file:
- YAML
1 2 3 4 5 6 7
# config/packages/sonata_admin.yaml 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
7.2. Creating a custom RouteBuilder¶
To create your own RouteBuilder create the PHP class and register it as a service:
namespace App\Route;
use Sonata\AdminBundle\Builder\RouteBuilderInterface;
use Sonata\AdminBundle\Admin\AdminInterface;
use Sonata\AdminBundle\Route\PathInfoBuilder;
use Sonata\AdminBundle\Route\RouteCollection;
class EntityRouterBuilder extends PathInfoBuilder implements RouteBuilderInterface
{
/**
* @param AdminInterface $admin
* @param RouteCollection $collection
*/
public function build(AdminInterface $admin, RouteCollection $collection)
{
parent::build($admin, $collection);
$collection->add('yourSubAction');
// The create button will disappear, delete functionality will be disabled as well
// No more changes needed!
$collection->remove('create');
$collection->remove('delete');
}
}
- YAML
1 2 3 4 5 6 7
# config/services.yaml services: app.admin.entity_route_builder: class: App\Route\EntityRouterBuilder arguments: - '@sonata.admin.audit.manager'
- XML
1 2 3 4 5
<!-- config/services.xml --> <service id="app.admin.entity_route_builder" class="App\Route\EntityRouterBuilder"> <argument type="service" id="sonata.admin.audit.manager"/> </service>
7.3. 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
:
- YAML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# config/services.yaml app.admin.person: class: App\Admin\PersonAdmin arguments: - ~ - App\Entity\Person - ~ calls: - - setSubClasses - student: App\Entity\Student teacher: App\Entity\Teacher tags: - { name: sonata.admin, manager_type: orm, group: "admin", label: "Person" }
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14
<!-- config/services.xml --> <service id="app.admin.person" class="App\Admin\PersonAdmin"> <argument/> <argument>App\Entity\Person</argument> <argument></argument> <call method="setSubClasses"> <argument type="collection"> <argument key="student">App\Entity\Student</argument> <argument key="teacher">App\Entity\Teacher</argument> </argument> </call> <tag name="sonata.admin" manager_type="orm" group="admin" label="Person"/> </service>
You will need to change the way forms are configured in order to take into account these new subclasses:
// src/Admin/PersonAdmin.php
protected function configureFormFields(FormMapper $formMapper)
{
$subject = $this->getSubject();
$formMapper
->add('name')
;
if ($subject instanceof Teacher) {
$formMapper->add('course', 'text');
}
elseif ($subject instanceof Student) {
$formMapper->add('year', 'integer');
}
}
7.6. 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 a
custom layout or don’t need such behavior, add the no-stretch
class
to the <html>
tag.
1 2 3 | {# templates/standard_layout.html.twig #}
{% block html_attributes %}class="no-js no-stretch"{% endblock %}
|
7.7. 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:
// src/Admin/PostAdmin.php
final class CustomAdmin extends AbstractAdmin
{
protected $accessMapping = [
'myCustomFoo' => 'EDIT',
'myCustomBar' => ['EDIT', 'LIST'],
];
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // src/Controller/CustomCRUDController.php
class CustomCRUDController extends CRUDController
{
public function myCustomFooAction()
{
$this->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 overriding checkAccess
function:
// src/Admin/CustomAdmin.php
final class CustomAdmin extends AbstractAdmin
{
public function checkAccess($action, $object = null)
{
$this->customAccessLogic();
}
}
7.8. Use your own custom controller as default¶
By default, CRUDController
is the controller used when no controller has been specified. You can modify this by
adding the following in the configuration:
- YAML
1 2 3 4
# config/packages/sonata_admin.yaml sonata_admin: default_controller: App\Controller\DefaultCRUDController