sonata-project/doctrine-orm-admin-bundle
Installation:
composer require sonata-project/doctrine-orm-admin-bundle
Ensure SonataDoctrineORMAdminBundle is enabled in config/bundles.php:
return [
// ...
SonataDoctrineORMAdminBundle\SonataDoctrineORMAdminBundle::class => ['all' => true],
];
First Admin Class:
Generate a CRUD admin for an existing entity (e.g., App\Entity\User):
php bin/console generate:sonata-admin App\Entity\User
This creates a service and admin class (e.g., UserAdmin.php) in src/Admin/.
Register the Admin:
Add the admin service to config/packages/sonata_admin.yaml:
sonata_admin:
options:
html5_entities: true
security:
handler: sonata.admin.security.handler.role
assets:
extra_css:
- 'bundles/sonataadmin/css/styles.css'
Tag the admin service in src/Admin/UserAdmin.php:
class UserAdmin extends AbstractAdmin
{
protected function configureServices()
{
$this->adminCode = 'user';
}
}
First Use Case:
Access /admin/app_user to see the auto-generated CRUD interface for User entities.
config/packages/sonata_admin.yamlsrc/Admin/*Admin.phptemplates/SonataAdminBundle/CRUD/* (override defaults here).Entity CRUD:
Extend AbstractAdmin and override methods for custom logic:
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->add('id')
->add('email')
->add('roles', null, ['editable' => false]);
}
Form Customization:
Use FormMapper in configureFormFields() to modify fields:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->tab('General')
->with('Details')
->add('email')
->add('plainPassword', 'text', ['required' => false])
->end()
->end();
}
Batch Actions:
Enable batch operations in configureDatagridFilters() and configureBatchActions():
protected function configureBatchActions(BatchAction $batchAction)
{
$batchAction
->add('delete')
->add('export', null, ['label' => 'Export']);
}
Filtering:
Customize filters in configureDatagridFilters():
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('email')
->add('roles', null, ['field_type' => 'sonata_type_model_list']);
}
Dependency Injection:
Inject services into admin classes via configureServices():
public function configureServices()
{
$this->services = [
'sonata.admin.user' => [
'calls' => [
['service', 'setMailer', ['@sonata.mailer.mailer']],
],
],
];
}
Event Listeners:
Use Symfony events (e.g., sonata.admin.event.configure) to modify behavior globally:
// src/EventListener/AdminListener.php
public function onConfigure(ConfigureEvent $event)
{
$event->getAdminPool()->getAdminByAdminCode('user')->setTemplate('base', 'custom_base.html.twig');
}
Template Overrides:
Override Sonata’s default templates by copying them to templates/SonataAdminBundle/CRUD/ and modifying:
{# templates/SonataAdminBundle/CRUD/base_list_field.html.twig #}
{% extends '@SonataAdmin/CRUD/base_list_field.html.twig' %}
{% block field %}{{ field }} (Custom suffix){% endblock %}
API Integration:
Use Sonata’s built-in REST support by enabling sonata_admin_rest and configuring routes:
# config/routes/sonata_admin.yaml
sonata_admin_rest:
resource: "@SonataAdminBundle/Resources/config/routing/sonata_admin_rest.xml"
prefix: /api
Dynamic Admin Generation: Dynamically register admins via a compiler pass or service loader:
// src/DependencyInjection/Compiler/AdminPass.php
public function process(ContainerBuilder $container)
{
$definition = $container->findDefinition('sonata.admin.pool');
$definition->addMethodCall('addAdmin', ['App\Admin\UserAdmin']);
}
Multi-Tenancy:
Override getEntityManager() to scope queries per tenant:
public function getEntityManager()
{
return $this->getConfigurationPool()->getContainer()->get('tenant.entity_manager');
}
Custom Actions: Add custom actions to the action menu:
protected function configureActions()
{
$actions = [
'list' => ['icon' => 'fa-list'],
'custom_action' => ['label' => 'Custom', 'icon' => 'fa-rocket'],
];
return $actions;
}
Field Descriptions: Add tooltips or help text to fields:
$formMapper->add('email', 'text', [
'help' => 'Required for login.',
'attr' => ['placeholder' => 'user@example.com'],
]);
Caching Issues: Clear Sonata’s cache after changes:
php bin/console sonata:cache:clear
Or manually clear the sonata_admin cache:
php bin/console cache:clear
Entity Not Found:
Ensure the admin’s adminCode matches the entity’s short class name (e.g., UserAdmin for App\Entity\User).
Permission Denied:
Verify ROLE_SONATA_ADMIN is assigned to users. Customize roles in configureSecurity():
protected function configureSecurity()
{
$security = $this->getSecurity();
$security->addPermission('EDIT', 'POST_EDIT');
}
Template Not Overridden:
Ensure template files are placed in templates/SonataAdminBundle/ (not templates/bundles/sonataadmin/).
Doctrine Query Issues:
Override createQuery() or createListQuery() to modify queries:
public function createQuery($context = 'list')
{
$query = parent::createQuery($context);
$query->andWhere('u.enabled = :enabled');
$query->setParameter('enabled', true);
return $query;
}
Enable Debug Mode:
Set sonata_admin.debug to true in config/packages/sonata_admin.yaml to see SQL queries and admin events.
Log Admin Events:
Enable logging for sonata.admin in config/packages/monolog.yaml:
handlers:
sonata_admin:
type: stream
path: "%kernel.logs_dir%/sonata_admin.log"
level: debug
channels: ["sonata.admin"]
Dump Admin Configuration: Use the debug command to inspect admin settings:
php bin/console debug:sonata-admin
Check for Deprecations: Sonata 4.x may deprecate some 3.x features. Review the upgrade guide.
Datagrid Default Order:
Set default sorting in configureDatagrid():
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper->add('id', null, [], null, ['order' => 'DESC']);
}
Mass Actions:
Ensure sonata.admin.security.handler is configured to allow mass actions:
sonata_admin:
security:
handler: sonata.admin.security.handler.role
information:
ROLE_SONATA_ADMIN: [MASTER]
Field Types:
Use Sonata’s custom field types (e.g., sonata_type_model_list) for relationships
How can I help you explore Laravel packages today?