Installation
composer require effiana/easyadmin-bundle
Register the bundle in config/bundles.php:
return [
// ...
Effiana\EasyAdminBundle\EasyAdminBundle::class => ['all' => true],
];
First Backend
Create a CRUD controller for an entity (e.g., Post):
php bin/console make:crud Post
Configure the route in config/routes.yaml:
easy_admin:
resource: '@EasyAdminBundle/Controller/EasyAdminController.php'
type: 'annotation'
prefix: '/admin'
First Use Case
Access /admin to see a pre-built admin panel for your Post entity. Customize fields via YAML/annotation in src/Entity/Post.php:
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Config\Field;
#[EasyAdmin\Config]
class Post
{
#[Field]
public $title;
#[Crud]
public function configureFields(string $pageName): iterable
{
return [
Field\TextField::new('title'),
Field\TextareaField::new('content'),
];
}
}
Entity Configuration
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
#[Crud]
#[Actions(list: [Action\DetailAction::new(), Action\EditAction::new()])]
class User {}
Field Customization
AssociationField, CollectionField).#[Field(properties: ['form_type' => EmailType::class])]
public $email;
List and Filtering
configureListFields():
public function configureListFields(string $pageName): iterable
{
return [
Field\TextField::new('title')->hideOnDetail(),
Field\DateTimeField::new('createdAt')->format('Y-m-d'),
];
}
configureFilters():
public function configureFilters(string $pageName): iterable
{
return [
Filter\TextFilter::new('title'),
Filter\DateFilter::new('createdAt'),
];
}
Actions and Buttons
#[Action('publish', icon: 'fas fa-bullhorn', label: 'Publish')]
public function publishAction(EntityManagerInterface $em, $entity): void
{
$entity->setStatus('published');
$em->flush();
}
Security and Permissions
# config/packages/easy_admin.yaml
easy_admin:
design:
menu:
- { label: 'Dashboard', icon: 'fas fa-home', route: 'app_dashboard', role: 'ROLE_ADMIN' }
Integration with Forms
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use Symfony\Component\Form\AbstractType;
class CustomFieldType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('custom_field', TextType::class);
}
}
#[Field(form_type: CustomFieldType::class)]
public $customField;
Entity Requirements
SingleTableInheritance) are unsupported. Use MappedSuperclass or flatten hierarchies.->setFetch('EAGER') in configureFields().Caching Quirks
php bin/console cache:clear
config/packages/easy_admin.yaml:
easy_admin:
design:
assets:
css:
all: ['bundles/easyadmin/css/easyadmin.all.css']
js:
all: ['bundles/easyadmin/js/easyadmin.all.js']
Field Overrides
Field\AssociationField::new('author')->autocomplete()->setTargetEntityId('App\Entity\User');
Translation Issues
# config/packages/framework.yaml
framework:
translator:
paths:
- '%kernel.project_dir%/translations'
defaults:
- '%locale%'
Performance with Large Datasets
public function configureQuery(string $entityClass): QueryBuilder
{
return parent::createQueryBuilder('e')
->where('e.status = :status')
->setParameter('status', 'active');
}
Debugging Tips
# config/packages/dev/debug.yaml
framework:
profiler: { only_exceptions: false }
Custom Templates
templates/EasyAdminBundle/:
{# templates/EasyAdminBundle/Crud/list.html.twig #}
{% extends '@EasyAdmin/crud/list.html.twig' %}
{% block easyadmin_list_row_actions %}
{{ parent() }}
<a href="{{ path('app_custom_action', { id: entity.id }) }}">Custom</a>
{% endblock %}
Event Listeners
prePersist, postRemove):
use EasyCorp\Bundle\EasyAdminBundle\Event\EasyAdminEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class CustomSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
EasyAdminEvents::PRE_PERSIST => 'onPrePersist',
];
}
public function onPrePersist($event)
{
$entity = $event->getEntity();
$entity->setCreatedAt(new \DateTime());
}
}
services.yaml:
services:
App\EventListener\CustomSubscriber:
tags:
- { name: kernel.event_subscriber }
Dynamic Configuration
AdminContext to conditionally modify behavior:
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
public function configureFields(string $pageName, AdminContext $context): iterable
{
if ($context->getEntity()->getId() === 1) {
return [Field\TextField::new('title')->onlyOnDetail()];
}
return [Field\TextField::new('title')];
}
Asset Management
# config/packages/easy_admin.yaml
easy_admin:
design:
assets:
extra_css:
- 'bundles/app/css/admin-custom.css'
extra_js:
- 'bundles/app/js/admin-custom.js'
How can I help you explore Laravel packages today?