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
):
# 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'
<!-- 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>
# 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' }
<!-- 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:
# 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
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');
}
}
# config/services.yaml
services:
app.admin.entity_route_builder:
class: App\Route\EntityRouterBuilder
arguments:
- '@sonata.admin.audit.manager'
<!-- config/services.xml -->
<service id="app.admin.entity_route_builder" class="App\Route\EntityRouterBuilder">
<argument type="service" id="sonata.admin.audit.manager"/>
</service>
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
:
# 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" }
<!-- 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');
}
}
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.
{# templates/standard_layout.html.twig #}
{% block html_attributes %}class="no-js no-stretch"{% endblock %}
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'],
];
}
// 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();
}
}
By default, CRUDController
is the controller used when no controller has been specified. You can modify this by
adding the following in the configuration:
# config/packages/sonata_admin.yaml
sonata_admin:
default_controller: App\Controller\DefaultCRUDController
Found a typo? Something is wrong in this documentation? Just fork and edit it!