dariotilgner/easyadmin-extension-bundle
Installation Add the bundle via Composer:
composer require alterphp/easyadmin-extension-bundle
Register the bundle in config/bundles.php:
return [
// ...
AlterPhp\EasyAdminExtensionBundle\AlterPhpEasyAdminExtensionBundle::class => ['all' => true],
];
First Use Case: Customizing CRUD Actions
Extend a CRUD controller by overriding the configureActions() method in your entity CRUD class:
use AlterPhp\EasyAdminExtensionBundle\Extension\Action\ActionExtension;
class PostCrudController extends EasyAdminCrudController
{
public static function getEntityFqcn(): string
{
return Post::class;
}
public function configureActions(Actions $actions): Actions
{
$actions = parent::configureActions($actions);
$actions->add(ActionExtension::create('custom_action', 'Custom Action', 'fas fa-rocket')
->linkToCrudAction('customAction')
);
return $actions;
}
public function customAction(EntityManagerInterface $em, $id): Response
{
// Custom logic
return $this->redirectTo('index');
}
}
Where to Look First
src/Extension/ in the bundle for available extensions (e.g., ActionExtension, FieldExtension).tests/ directory for practical examples of integration.Use ActionExtension to add custom actions (e.g., bulk operations, custom redirects):
$actions->add(ActionExtension::create('export_csv', 'Export CSV')
->linkToRoute('app_export_csv', ['entity' => 'post'])
->displayIf(fn($entity) => $entity->isExportable())
);
Override field rendering with FieldExtension:
use AlterPhp\EasyAdminExtensionBundle\Extension\Field\FieldExtension;
public function configureFields(string $pageName, FieldCollection $fields): FieldCollection
{
$fields = parent::configureFields($pageName, $fields);
if ($pageName === 'edit') {
$fields->add(FieldExtension::create('custom_field')
->setTemplate('@EasyAdminExtension/custom_field.html.twig')
->setLabel('Custom Field')
->setFormType(CustomFieldType::class)
);
}
return $fields;
}
Dynamically modify the menu or routes:
use AlterPhp\EasyAdminExtensionBundle\Extension\Menu\MenuExtension;
public function configureMenuItems(MenuItemCollection $menuItems): MenuItemCollection
{
$menuItems = parent::configureMenuItems($menuItems);
$menuItems->addMenuItem(MenuExtension::create('dashboard_custom')
->setLabel('Custom Dashboard')
->setRoute('app_custom_dashboard')
->setPosition(10)
);
return $menuItems;
}
Note: This bundle’s list filters are not compatible with EasyAdmin’s dynamic filters. Use static filters only:
use AlterPhp\EasyAdminExtensionBundle\Extension\Filter\FilterExtension;
public function configureListFilters(ListBuilder $builder): ListBuilder
{
$builder->addListFilter(
FilterExtension::create('custom_filter')
->setFormType(CustomFilterType::class)
->setLabel('Custom Filter')
);
return $builder;
}
Dependency Injection Inject the extension services directly into your CRUD controllers:
public function __construct(
private ActionExtension $actionExtension,
private FieldExtension $fieldExtension
) {}
Twig Templates
Override default templates by copying them from the bundle’s Resources/views/ to your project’s templates/EasyAdminExtension/.
Event Listeners Use Symfony events to dynamically modify behavior:
// config/services.yaml
services:
App\EventListener\EasyAdminExtensionListener:
tags:
- { name: kernel.event_listener, event: easyadmin.extension.action, method: onActionExtension }
Version Compatibility
3.x branch.Dynamic Filter Conflict
config/packages/easy_admin.yaml:
easy_admin:
design:
assets:
dynamic_filters: false
Menu Permissions
v2.2.0 and v2.2.1 of EasyAdmin lack native menu permissions, which may cause issues.>=2.2.2 or manually implement permission checks.Template Overrides
debug:container --parameter easyadmin.extension.templates to locate template paths.Action Link Routing
php bin/console debug:router and use absolute routes when possible.Extension Not Loading
config/bundles.php.3.x branch).Field/Action Not Rendering
parent::configureFields() or parent::configureActions().php bin/console cache:clear
Permission Denied
security.yaml:
access_control:
- { path: ^/admin/custom_action, roles: ROLE_CUSTOM_ACTION }
Reusable Extensions Create base CRUD controllers to share common extensions:
abstract class BaseCrudController extends EasyAdminCrudController
{
protected function addCommonExtensions(Actions $actions): Actions
{
$actions->add(ActionExtension::create('audit_log', 'View Audit Log'));
return $actions;
}
}
Conditional Extensions Use closures to conditionally add extensions:
$actions->addIf(
fn() => auth()->user()->hasRole('ADMIN'),
ActionExtension::create('delete_all', 'Delete All')
);
Performance
->setTemplate() for custom fields to avoid unnecessary database queries.Testing
Test extensions in isolation using Symfony’s KernelTestCase:
public function testCustomAction()
{
$client = static::createClient();
$client->loginUser(self::createAdminUser());
$crawler = $client->request('GET', '/admin/post/custom_action/1');
$this->assertResponseIsSuccessful();
}
Bundle Updates
alterphp/easyadmin-extension-bundle (though inactive, check for forks).How can I help you explore Laravel packages today?