Launching an Internal Tool Quickly Using EasyAdmin
Why choose EasyAdmin
EasyAdmin is a lightweight, Symfony-native admin generator that lets you scaffold CRUD interfaces rapidly. It reduces boilerplate, enforces consistent UI patterns, and integrates with Symfony security, forms, and Doctrine out of the box.
Quick project setup (assumptions)
- PHP 8.1+ and Composer installed
- Symfony 6.x project initialized
- Doctrine ORM configured and a User or target entity available
Step 1 — Install EasyAdmin
Run:
composer require easycorp/easyadmin-bundle
Then enable the bundle (Symfony Flex handles this automatically in recent Symfony versions).
Step 2 — Generate an Admin Dashboard
Create a Dashboard controller:
// src/Controller/Admin/DashboardController.phpnamespace App\Controller\Admin; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Routing\Annotation\Route; class DashboardController extends AbstractDashboardController{ #[Route(‘/admin’, name: ‘admin’)] public function index(): Response { return \(this->render('admin/dashboard.html.twig'); }}</code></pre></div></div><p>You can return EasyAdmin's default dashboard or customize templates.</p><h3>Step 3 — Create CRUD controllers</h3><p>Generate CRUD for an entity (example: Product):</p><div><div></div><div><div><button title="Download file" type="button"><svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" width="14" height="14" color="currentColor"><path fill="currentColor" d="M8.375 0C8.72 0 9 .28 9 .625v9.366l2.933-2.933a.625.625 0 0 1 .884.884l-2.94 2.94c-.83.83-2.175.83-3.005 0l-2.939-2.94a.625.625 0 0 1 .884-.884L7.75 9.991V.625C7.75.28 8.03 0 8.375 0m-4.75 13.75a.625.625 0 1 0 0 1.25h9.75a.625.625 0 1 0 0-1.25z"></path></svg></button><button title="Copy Code" type="button"><svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" width="14" height="14" color="currentColor"><path fill="currentColor" d="M11.049 5c.648 0 1.267.273 1.705.751l1.64 1.79.035.041c.368.42.571.961.571 1.521v4.585A2.31 2.31 0 0 1 12.688 16H8.311A2.31 2.31 0 0 1 6 13.688V7.312A2.31 2.31 0 0 1 8.313 5zM9.938-.125c.834 0 1.552.496 1.877 1.208a4 4 0 0 1 3.155 3.42c.082.652-.777.968-1.22.484a2.75 2.75 0 0 0-1.806-2.57A2.06 2.06 0 0 1 9.937 4H6.063a2.06 2.06 0 0 1-2.007-1.584A2.75 2.75 0 0 0 2.25 5v7a2.75 2.75 0 0 0 2.66 2.748q.054.17.123.334c.167.392-.09.937-.514.889l-.144-.02A4 4 0 0 1 1 12V5c0-1.93 1.367-3.54 3.185-3.917A2.06 2.06 0 0 1 6.063-.125zM8.312 6.25c-.586 0-1.062.476-1.062 1.063v6.375c0 .586.476 1.062 1.063 1.062h4.374c.587 0 1.063-.476 1.063-1.062V9.25h-1.875a1.125 1.125 0 0 1-1.125-1.125V6.25zM12 8h1.118L12 6.778zM6.063 1.125a.813.813 0 0 0 0 1.625h3.875a.813.813 0 0 0 0-1.625z"></path></svg></button></div></div><div><pre><code>php bin/console make:admin:crud App\\Entity\\Product</code></pre></div></div><p>This creates a controller under src/Controller/Admin with list, detail, new, edit, delete actions wired to the Product entity.</p><h3>Step 4 — Configure fields and behaviors</h3><p>Edit the generated CRUD controller to choose fields, add permissions, and customize forms:</p><div><div>php</div><div><div><button title="Download file" type="button"><svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" width="14" height="14" color="currentColor"><path fill="currentColor" d="M8.375 0C8.72 0 9 .28 9 .625v9.366l2.933-2.933a.625.625 0 0 1 .884.884l-2.94 2.94c-.83.83-2.175.83-3.005 0l-2.939-2.94a.625.625 0 0 1 .884-.884L7.75 9.991V.625C7.75.28 8.03 0 8.375 0m-4.75 13.75a.625.625 0 1 0 0 1.25h9.75a.625.625 0 1 0 0-1.25z"></path></svg></button><button title="Copy Code" type="button"><svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" width="14" height="14" color="currentColor"><path fill="currentColor" d="M11.049 5c.648 0 1.267.273 1.705.751l1.64 1.79.035.041c.368.42.571.961.571 1.521v4.585A2.31 2.31 0 0 1 12.688 16H8.311A2.31 2.31 0 0 1 6 13.688V7.312A2.31 2.31 0 0 1 8.313 5zM9.938-.125c.834 0 1.552.496 1.877 1.208a4 4 0 0 1 3.155 3.42c.082.652-.777.968-1.22.484a2.75 2.75 0 0 0-1.806-2.57A2.06 2.06 0 0 1 9.937 4H6.063a2.06 2.06 0 0 1-2.007-1.584A2.75 2.75 0 0 0 2.25 5v7a2.75 2.75 0 0 0 2.66 2.748q.054.17.123.334c.167.392-.09.937-.514.889l-.144-.02A4 4 0 0 1 1 12V5c0-1.93 1.367-3.54 3.185-3.917A2.06 2.06 0 0 1 6.063-.125zM8.312 6.25c-.586 0-1.062.476-1.062 1.063v6.375c0 .586.476 1.062 1.063 1.062h4.374c.587 0 1.063-.476 1.063-1.062V9.25h-1.875a1.125 1.125 0 0 1-1.125-1.125V6.25zM12 8h1.118L12 6.778zM6.063 1.125a.813.813 0 0 0 0 1.625h3.875a.813.813 0 0 0 0-1.625z"></path></svg></button></div></div><div><pre><code>// in ProductCrudController.phppublic function configureFields(string \)pageName): iterable{ return [ IdField::new(‘id’)->onlyOnIndex(), TextField::new(‘name’), TextareaField::new(‘description’), MoneyField::new(‘price’)->setCurrency(‘USD’), AssociationField::new(‘category’), BooleanField::new(‘published’), ];}
Use conditional field display by inspecting $pageName and add filters, search, or batch actions as needed.
Step 5 — Integrate security and access control
Use Symfony security to restrict admin area:
- Define roles (e.g., ROLE_ADMIN)
- Protect routes in security.yaml or via annotations Example:
access_control: - { path: ^/admin, roles: ROLE_ADMIN }
Step 6 — Add custom pages and widgets
Create custom menu items in DashboardController and add custom CRUD actions or dashboard widgets:
public function configureMenuItems(): iterable{ yield MenuItem::linkToDashboard(‘Dashboard’, ‘fa fa-home’); yield MenuItem::linkToCrud(‘Products’, ‘fa fa-box’, Product::class); yield MenuItem::linkToRoute(‘Custom Report’, ‘fa fa-chart-line’, ‘admin_report’);}
Build custom controllers or services to render charts (Chart.js) or KPI blocks.
Step 7 — Polish UI and UX
- Customize templates: override EasyAdmin templates in templates/bundles/EasyAdminBundle/.
- Use assets: add CSS/JS through Symfony Webpack Encore or Vite.
- Improve forms: add validation, help texts, and inline edits.
Deployment checklist
- Ensure production environment variables are set.
- Migrate database changes:
php bin/console doctrine:migrations:migrate. - Configure web server to serve Symfony and secure /admin with HTTPS.
- Create initial admin users or seed data.
Tips for speed
- Start with default CRUD and iterate—don’t over-customize initially.
- Reuse existing entities and relations; avoid new schema work early.
- Use field groups and property_form_type to speed form building.
- Leverage EasyAdmin events to inject small custom logic without rewriting CRUD.
Example timeline (1–2 days)
- Hour 0–2: Install EasyAdmin, create dashboard, wire routes.
- Hour 2–6: Generate CRUD for core entities and configure fields.
- Hour 6–10: Add security, basic styling, and seed admin user.
- Hour 10–16: Add a dashboard widget, custom action, QA and deploy.
Conclusion
EasyAdmin lets teams launch internal admin tools fast by automating common CRUD tasks while staying fully extensible. Start with defaults, secure routes, and iterate toward tailored workflows as user needs become clear.
Leave a Reply