Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Easyadmin Bundle Laravel Package

easycorp/easyadmin-bundle

EasyAdmin builds beautiful, responsive admin panels for Symfony apps with no CSS required. Run three commands to generate a dashboard and CRUD controllers, then manage your data through a modern UI with light and dark modes and multiple dashboards. Free and fully documented.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require easycorp/easyadmin-bundle
    

    Register the bundle if it isn't auto-discovered:

    // config/bundles.php
    return [
        // ...
        EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true],
    ];
    
  2. Publish assets (needed after every upgrade that touches CSS/JS/icons):

    php bin/console assets:install
    # or, when using AssetMapper:
    php bin/console importmap:install
    
  3. Generate a dashboard

    php bin/console make:admin:dashboard
    

    Creates a dashboard controller rendering at /admin with the default layout and menu.

  4. Generate CRUD for an entity

    php bin/console make:admin:crud
    

    Pick an entity (e.g. App\Entity\Post); you get a controller covering index, new, edit, detail and delete.

  5. Open /admin and authenticate with your app's security setup (security.yaml).

Where to Look First

  • The generated dashboard controller — menu items and the dashboard route live here.
  • The generated *CrudController — configureFields(), configureActions() and configurePages() are the three hooks you'll touch 90% of the time.
  • The UI Kit (new in 5.7) — a development-only tool that renders every Twig component, prop and form field in one place. Use it as a copy-paste style guide before hand-writing markup or CSS. It ships alongside the refreshed EasyAdmin profiler panel; when you're unsure which component/prop exists, check the UI Kit before reading vendor templates.

First Use Case: CRUD for a Blog Post

// src/Controller/Admin/PostCrudController.php
public static function getEntityFqcn(): string
{
    return Post::class;
}

public function configureFields(string $pageName): iterable
{
    return [
        Field::new('title')->setLabel('Blog Post Title')->required(),
        Field::new('content')->onlyOnForms()->setFormTypeOption('attr', ['rows' => 8]),
        Field::new('publishedAt')->setFormTypeOption('widget', 'single_text'),
    ];
}

Then register it in the dashboard menu:

public function configureMenuItems(): iterable
{
    yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home');
    yield MenuItem::linkToCrud('Posts', 'fas fa-newspaper', Post::class);
}

Visit /admin/post — list, filters, pagination, create/edit forms and delete are wired up.


Implementation Patterns

1. CRUD Controllers as the Unit of Work

The everyday workflow is: generate a controller, then override small hooks instead of rewriting pages.

public function configureFields(string $pageName): iterable
{
    return [
        Field::new('title')->setLabel('Title')->required()->autocomplete(),
        Field::new('slug')->hideOnIndex(),
        Field::new('author')->setFormTypeOption('by_reference', false),
        Field::new('image')->setFormType(FileFieldType::class)->setRequired(false),
        Field::new('content')->onlyOnDetail(),
        Field::new('createdAt')->hideOnForm(),
    ];
}

Useful patterns:

  • onlyOnIndex(), onlyOnForms(), onlyOnDetail(), hideOnIndex() for page-scoped fields.
  • setPermission('ROLE_EDITOR') for field-level visibility — the field is removed from forms and list output, not just visually hidden.
  • setFormTypeOption() to pass through Symfony form type options rather than subclassing a field.

2. Twig Components Instead of Hand-Rolled Markup

5.7 documents the props and blocks of the built-in Twig components, and the UI Kit renders them live. For custom templates and dashboards, prefer components over raw HTML so styling tracks the theme:

{# Icon component now accepts a size prop #}
<twig:ea:Icon name="fa:solid:user" size="lg" />

<twig:ea:Badge color="success">Published</twig:ea:Badge>

When a component supports blocks, the docs/UI Kit list the block names — use them instead of CSS overrides wherever possible.

3. Form Layout and Tabs

Group long forms into fieldsets/tabs, and pin tab identifiers when you need stability:

yield FormField::addTab('Content', 'fa fa-pen');
yield FormField::addPanel('Basics');

yield Field::new('title');
yield Field::new('summary');

FormField::addTab('SEO')->setTabId('seo');   // new in 5.7
yield Field::new('metaTitle');
yield Field::new('metaDescription');

setTabId() matters when you:

  • deep-link to a tab (#seo) from another page or a "next error field" flow,
  • drive JS off tab ids,
  • write functional tests asserting which tab is active.

Without it, ids are generated and can shift when you reorder fields.

4. Actions, Batches and Modals

public function configureActions(Actions $actions): Actions
{
    $publish = Action::new('publish', 'Publish')
        ->linkToCrudAction('publishPost')
        ->displayIf(fn (Post $post) => !$post->isPublished());

    return $actions
        ->add(Crud::PAGE_INDEX, Action::DETAIL)
        ->add(Crud::PAGE_DETAIL, $publish)
        ->addBatchAction(BatchAction::new('publish_all', 'Publish all')->linkToCrudAction('publishBatch'));
}

Keep mutation actions on POST (a custom CRUD action with #[Route(methods: ['POST'])] or EasyAdmin's action handling) rather than GET links with side effects. Custom action modals got design fixes in 5.7, so verify your custom modal markup against the UI Kit if you reimplemented any.

5. Dashboards, Menus and Permissions

yield MenuItem::linkToCrud('Users', 'fas fa-users', User::class)
    ->setPermission('ROLE_ADMIN');

yield MenuItem::section('Reports');
yield MenuItem::linkToRoute('Sales', 'fas fa-chart-bar', 'app_reports_sales');
  • One dashboard per audience (make:admin:dashboard again, then set #[AdminDashboard]/route prefix accordingly) and gate them in security.yaml.
  • Prefer setPermission() / setPermission(SomeVoter::class, 'edit') on menu items, fields and actions over duplicating controllers per role.
  • If you need per-request trimming of the menu, use a ConfigureMenuEvent listener rather than overriding configureMenuItems() with request state.

6. Custom Templates and Theming

Override by path under templates/bundles/EasyAdminBundle/... — never edit vendor/.

  • Override only what you must (crud/index.html.twig, crud/detail.html.twig, layout.html.twig); wholesale copies drift and break on minor upgrades.
  • Re-run assets:install/importmap:install after upgrades so icon and CSS assets match the new bundle version.
  • Theme radius 0 now renders switches square — if you set radius: 0 and previously patched CSS for toggle shape, drop that patch.

7. Profiler-Driven Debugging

The EasyAdmin profiler panel was reworked in 5.7. On any admin page it shows the resolved AdminContext, the current CRUD controller/action, the field list actually rendered, and the query used for the index. When a field "disappears", a permission check fails, or you get an unexpected 404, open the panel first — it usually names the culprit without a dump().


Gotchas and Tips

  • Unknown ?routeName= is now a 404, not a 500. If you generated links by string (including a typo'd route name in linkToRoute()), you'll get a bare 404 instead of a loud exception. Add a smoke test that crawls the menu, or validate route names in a menu listener.

  • setEventDispatcher() / CRUD pages now use the event dispatcher contract. If you extended a CRUD controller or a service and typed the setter against Symfony's concrete dispatcher, switch to Psr\EventDispatcher\EventDispatcherInterface. Autowire the interface, not EventDispatcher. php bin/console debug:autowiring event (the 5.7 docs now describe the listed types) is the quickest way to confirm what's injectable.

  • Empty file fields now save null. Previously you could end up with an empty string (or a stale path) persisted. Consequences:

    • Make the column nullable, or add a #[Assert\NotNull]/setRequired(true) if the file is mandatory.
    • NOT NULL DB columns will now raise an integrity error on "clear the upload" instead of silently storing ''.
    • Re-check any custom setUploadDir() / setFileConstraints() / setFormTypeOption('mapped', false) setup, plus listeners that assumed a string.
  • The leftover ea global Twig variable is gone. Custom templates using ea.field_value(...)-style access must move to the current API — inject/use AdminContext/EntityDto (available as template variables) or the ea() Twig function. Grep your templates/ for ea. before upgrading.

  • Tab ids are generated unless you pin them. Any JS or test keyed on #tab-... is fragile across field reorders; add ->setTabId('seo') and target that.

  • Icon sizing changed surface in 5.7 (size prop). If you wrapped icons in custom CSS to control dimensions, remove the hack and use the prop — otherwise icons will double-scale.

  • Re-run asset tooling after upgrading. Symptom of a stale install: square/round switches and tab paddings behaving inconsistently with the release notes. cache:clear alone does not reinstall CSS/JS.

  • Per-field vs per-action permissions are independent. Field::new('salary')->setPermission('ROLE_ADMIN') protects display, but the value is still submitted/handled if a form is crafted — enforce authorization in the action/controller or a voter, not only in configureFields().

  • by_reference => false on association fields is the usual fix when a collection isn't updated on the owning side; pair it with proper addX()/removeX() methods and cascade settings.

  • Don't copy vendor templates wholesale. Override the smallest possible template and rely on Twig components + the UI Kit for anything cosmetic; minor releases touch component markup frequently (tabs, modals, dropdowns in 5.7 alone).

  • Batch actions run per entity and can be slow. For large selections, queue a job per batch or restrict with ->setPermission() plus a max-selection guard; the default implementation iterates in-request.

  • Useful console commands when something behaves oddly:

    php bin/console debug:router | grep admin
    php bin/console debug:autowiring admin
    php bin/console cache:clear
    
  • Pro features are separate. Audit Log and Content Lock are EasyAdmin Pro (paid) and not part of this release; don't plan core features around them unless you've licensed them.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource