## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require sonata-project/admin-bundle
Add to config/bundles.php:
return [
// ...
SonataAdminBundle::class => ['all' => true],
];
Basic Admin Class:
Create a service for your entity admin (e.g., src/Admin/ProductAdmin.php):
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
class ProductAdmin extends AbstractAdmin
{
protected $datagridValues = [
'_page' => 1,
'_per_page' => 10,
];
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper->add('name');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->add('id')
->add('name')
->add('price');
}
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('General')
->add('name')
->add('price')
->end();
}
}
Register Admin:
Add to config/services.yaml:
services:
App\Admin\ProductAdmin:
tags: ['sonata.admin']
arguments: ['App\Entity\Product', App\Admin\ProductController::class, 'main', '@doctrine.orm.entity_manager', null, null]
Access Admin:
Visit /admin/app_product (route auto-generated from App\Entity\Product).
Generate Admin Skeleton:
Use the sonata:admin command:
php bin/console make:sonata-admin Product
This creates a basic admin class with pre-configured fields.
Customize Fields:
Override configureFormFields() and configureListFields() to tailor the UI to your needs.
Enable Permissions:
Configure security in config/packages/security.yaml:
access_control:
- { path: ^/admin/, roles: ROLE_ADMIN }
AbstractAdmin subclass for your entity.List Fields: Use ListMapper to define columns in the list view.
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->add('id', 'id', ['label' => 'ID'])
->add('name', null, ['label' => 'Product Name'])
->add('price', 'currency', ['label' => 'Price', 'currency' => 'USD']);
}
id, text, currency, date, etc.) or custom templates.Form Fields: Use FormMapper to define editable fields.
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('Details')
->add('name', 'text', ['label' => 'Product Name'])
->add('price', 'money', ['label' => 'Price', 'currency' => 'USD'])
->end();
}
with()/end() for tabbed interfaces.Filtering: Use DatagridMapper to add filters.
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('name')
->add('price', null, ['label' => 'Price', 'type' => 'range']);
}
Enable batch actions in the admin class:
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->add('name')
->add('_action', 'actions', [
'actions' => [
'edit' => [],
'delete' => [],
],
]);
}
protected function configureSideMenu(SideMenuMapper $sideMenuMapper, $action = 'list')
{
$sideMenuMapper
->addChild('Batch Actions', 'batch')
->addChild('Export', 'export', ['icon' => 'fa fa-download']);
}
protected function configureBatchActions(BatchMapper $batchMapper)
{
$batchMapper
->add('delete', null, ['label' => 'Delete']);
}
Override default templates by creating a templates directory in your admin bundle:
src/
Resources/
views/
Admin/
Product/
list.html.twig # Override list view
edit.html.twig # Override edit form
Handle relationships with sonata_type_model:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('categories', 'sonata_type_model', [
'btn_add' => 'Add',
'btn_delete' => 'Remove',
'btn_edit' => 'Edit',
'link_parameters' => ['context' => 'list'],
], [
'edit' => 'inline',
'inline' => 'table',
]);
}
Use ACL or voter-based permissions:
protected function configurePermissions()
{
return [
'edit' => 'ROLE_ADMIN',
'delete' => 'ROLE_SUPER_ADMIN',
'list' => 'IS_AUTHENTICATED_REMEMBERED',
];
}
Extend functionality by overriding controller methods:
public function prePersist($object)
{
$object->setCreatedAt(new \DateTime());
}
public function preUpdate($object)
{
$object->setUpdatedAt(new \DateTime());
}
sonata_type_model for entity relationships.$filterRepository = $this->getModelManager()->getFilterPool();
$filterRepository->addFilter('softdeleteable', \App\Filter\SoftDeleteFilter::class);
Extend Sonata's form types:
use Sonata\AdminBundle\Form\Type\CollectionType;
$formMapper->add('tags', CollectionType::class, [
'by_reference' => false,
], [
'edit' => 'inline',
'inline' => 'table',
]);
Use translation keys for labels:
$listMapper->add('name', null, ['label' => 'admin.product.name']);
Define translations in translations/messages.en.yaml:
admin:
product:
name: 'Product Name'
Customize CSS/JS:
public function getTemplateDirs()
{
return [__DIR__.'/../Resources/views'];
}
public function getBundle()
{
return new \App\AdminBundle\AdminBundle();
}
Listen to admin events:
use Sonata\AdminBundle\Event\ConfigureDatagridEvent;
$eventDispatcher->addListener(ConfigureDatagridEvent::class, function (ConfigureDatagridEvent $event) {
$event->getDatagridMapper()->add('custom_field');
});
setup_sticky_elements() and setup_readmore_elements() (deprecated in v4.37+).readmore-js → Stimulus).sonata_admin.php routing config is used (importing sonata_admin.xml is deprecated)._sonata_admin prefix for clarity.symfony/security-acl) is optional but required for advanced permissions. Explicitly add it:
composer require symfony/security-acl
configurePermissions() to avoid access errors.ProductAdmin:
src/
Resources/
views/
Admin/
Product/
list.html.twig
getTemplate() in the admin class to specify custom paths:
public function getTemplate($name)
{
return 'AppAdminBundle:Product:'.$name.'.html.twig';
}
How can I help you explore Laravel packages today?