javiereguiluz/easyadmin-bundle
EasyAdmin is a fast, modern admin generator for Symfony. Build beautiful back offices quickly with sensible defaults and powerful customization. Requires PHP 8.0.2+ and Symfony 5.4+; full documentation available on symfony.com.
Installation:
composer require easycorp/easyadmin-bundle
Ensure your project uses Symfony 5.4+ and PHP 8.0.2+.
Configure the Bundle:
Add to config/bundles.php:
return [
// ...
EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true],
];
Create a CRUD Controller:
Generate a basic CRUD controller for an entity (e.g., Product):
php bin/console make:crud Product
This auto-generates a controller extending AbstractCrudController.
Register the Controller:
Add the route to config/routes.yaml:
easy_admin:
resource: '@EasyAdminBundle/Controller/EasyAdminController.php'
type: 'annotation'
prefix: '/admin'
Access the Admin Panel:
Visit /admin in your browser. The bundle auto-detects entities with Doctrine annotations (e.g., @ORM\Entity).
configureFields() method in your CRUD controller to show/hide fields:
public function configureFields(string $pageName): iterable
{
return [
'id',
'name',
'price',
'createdAt' => ['type' => 'datetime'],
];
}
Entity Configuration:
@EasyAdmin\Config).use EasyCorp\Bundle\EasyAdminBundle\Config\Type;
/**
* @EasyAdmin\Config(
* type=Type::EDIT,
* items={
* "name",
* "price" => ["type" => Type::NUMBER]
* }
* )
*/
class Product {}
Customizing the Admin UI:
templates/EasyAdminBundle/crud/ (e.g., list.html.twig).assets/EasyAdminBundle/scss/_variables.scss.Advanced CRUD:
public function configureActions(Actions $actions): Actions
{
return $actions
->add(Crud::PAGE_INDEX, Action::DETAIL)
->add(Crud::PAGE_INDEX, Action::EDIT)
->add(Crud::PAGE_INDEX, Action::DELETE);
}
configureFields():
'name' => ['type' => 'string', 'filterable' => true],
Integration with Forms:
EasyAdmin\Field\AssociationField for relationships:
'category' => ['type' => AssociationField::class, 'entity' => Category::class],
EasyAdmin\Router\AdminUrlGenerator to generate admin URLs in API responses.ROLE_ADMIN):
# config/packages/security.yaml
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
Entity Auto-Detection:
@ORM\Entity. Explicitly register others in configureEntities():
public function configureEntities(EntityManager $entityManager): iterable
{
yield Product::class;
yield Category::class;
}
Field Type Mismatches:
Type::TEXT for string, Type::NUMBER for float).dd($entity) in a custom action to verify data structure.Caching Issues:
php bin/console cache:clear
config/packages/easy_admin.yaml for development:
easy_admin:
design:
assets:
cache: false
Permission Denied:
ROLE_ADMIN or custom roles are assigned to users. Check Symfony’s profiler (/_profiler) for errors.# config/packages/dev/easy_admin.yaml
easy_admin:
design:
template:
layout: 'EasyAdminBundle:layout.html.twig'
public function __invoke(Request $request): Response
{
$entity = $this->entityManager->getRepository($this->entityClass)->find(1);
\Log::debug('Entity data:', ['entity' => $entity]);
// ...
}
Custom Field Types:
Create a new field type by extending EasyAdmin\Field\FieldInterface:
class CustomField extends AbstractField
{
public static function new(): self
{
return new self();
}
public function renderCell(Field $field, $entityValue, Entity $entity): string
{
return '<span class="custom-style">' . $entityValue . '</span>';
}
}
Event Listeners:
Hook into lifecycle events (e.g., prePersist):
// src/EventListener/ProductListener.php
class ProductListener implements EventSubscriber
{
public static function getSubscribedEvents()
{
return [
Crud::ENTITY_PERSIST => 'onPersist',
];
}
public function onPersist(BeforeCrudEvent $event): void
{
$entity = $event->getEntity();
$entity->setSlug(Str::slug($entity->getName()));
}
}
API Mode: Enable API-only mode for headless admin:
easy_admin:
design:
assets:
extra_javascript: []
extra_stylesheets: []
EasyAdmin\Action\Action for custom bulk operations:
$actions->add(Crud::PAGE_INDEX, Action::NEW, 'New')
->linkToCrudAction('new');
use Gedmo\Mapping\Annotation as Gedmo;
/**
* @Gedmo\SoftDeleteable(fieldName="deletedAt")
*/
class Product {}
search, filters) in configureFields() to reduce load time.How can I help you explore Laravel packages today?