Installation
composer require edezacas/base-admin
Register the bundle in config/bundles.php (Symfony 4.4+):
return [
// ...
EDC\BaseAdminBundle\EDCBaseAdminBundle::class => ['all' => true],
];
Configure
Add to config/packages/edc_base_admin.yaml:
edc_base_admin:
site_name: 'MyApp Admin'
login_check: 'app_login' # Your login route
logout: 'app_logout' # Your logout route
admin_home: 'admin_dashboard' # Your admin home route
First Login Page
Create templates/login.html.twig:
{% include '@EDCBaseAdmin/login.html.twig' %}
Route it in routes.yaml:
app_login:
path: /admin/login
controller: App\Controller\AdminController::login
First Admin Layout
Create templates/admin/_layout.html.twig:
{% extends '@EDCBaseAdmin/base.html.twig' %}
{% block title %}Admin Panel{% endblock %}
{% block sidebar %}
<ul class="nav flex-column">
<li class="nav-item"><a href="{{ path('admin_dashboard') }}">Dashboard</a></li>
</ul>
{% endblock %}
First Admin Page
Create templates/admin/dashboard.html.twig:
{% extends 'admin/_layout.html.twig' %}
{% block content %}
<h1>Welcome to Admin Panel</h1>
{% endblock %}
Extend _layout.html.twig for all admin pages, then create individual pages (e.g., users.html.twig, settings.html.twig) extending the layout. Use the built-in Bootstrap 5 components for forms, modals, and alerts.
Authentication Flow
login_check and logout config routes for Symfony’s security system.App\Controller\AdminController (e.g., handle form submission, redirect after login).public function login(AuthenticationUtils $authenticationUtils): Response
{
$error = $authenticationUtils->getLastAuthenticationError();
return $this->render('login.html.twig', ['error' => $error]);
}
Layout Inheritance
@EDCBaseAdmin/base.html.twig via _layout.html.twig._layout.html.twig for each admin page (e.g., dashboard.html.twig).title: Page title (appears in <title> and sidebar).sidebar: Navigation menu (uses Bootstrap 5 nav classes).dropdown: User dropdown menu (e.g., profile, logout).footer: Custom footer content.content: Main page content.Routing
/admin (e.g., admin/dashboard)._route_name_or_url_to_* in config for flexibility (supports both route names and URLs).admin_dashboard:
path: /admin/dashboard
controller: App\Controller\Admin\DashboardController::index
Asset Management
_layout.html.twig if needed:
{% block stylesheets %}
{{ parent() }}
<link href="{{ asset('css/custom.css') }}" rel="stylesheet">
{% endblock %}
Form Handling
form-control, btn-primary) in templates.templates/admin/users/create.html.twig:
<form method="post">
<div class="mb-3">
<label class="form-label">Username</label>
<input type="text" name="username" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
Dynamic Content
return $this->render('admin/dashboard.html.twig', [
'stats' => $this->getStatsService()->getData(),
]);
{% for stat in stats %}
<div class="card">{{ stat.value }}</div>
{% endfor %}
Modals and Alerts
<!-- Modal -->
<div class="modal fade" id="confirmDelete">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">Are you sure?</div>
<div class="modal-footer">
<button class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<a href="{{ path('admin_users_delete', { id: user.id }) }}" class="btn btn-danger">Delete</a>
</div>
</div>
</div>
</div>
<!-- Alert -->
{% if success %}
<div class="alert alert-success">{{ success }}</div>
{% endif %}
Bundle Registration
bundles.php will silently fail (no errors, no assets).all environment.Route Configuration
_route_name_or_url_to_* in config requires either a valid route name or a full URL (e.g., /admin/login). Mixing these will break authentication.login_check: app_login # Route name (recommended)
# logout: /admin/logout # Avoid URLs unless necessary
Template Overrides
@EDCBaseAdmin/base.html.twig directly (instead of via _layout.html.twig) will overwrite all customizations for every page._layout.html.twig:
{% extends 'admin/_layout.html.twig' %} {# Correct #}
{% extends '@EDCBaseAdmin/base.html.twig' %} {# Avoid #}
Asset Loading
_layout.html.twig. Missing assets will break the layout.{{ asset() }} for local files and verify the bundle’s assets are loaded first:
{% block stylesheets %}
{{ parent() }} {# Load bundle's CSS first #}
<link href="{{ asset('css/admin.css') }}" rel="stylesheet">
{% endblock %}
jQuery Dependencies
{% block javascripts %}
{{ parent() }} {# Loads jQuery #}
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="{{ asset('js/admin.js') }}"></script>
{% endblock %}
Security
login_check route must be secured in security.yaml to prevent brute force attacks.firewalls:
main:
form_login:
login_path: app_login
check_path: app_login
logout: app_logout
remember_me:
secret: '%kernel.secret%'
lifetime: 86400 # 1 day
path: /
Debugging
php bin/console cache:clear
{{ dump(_context) }} in templates to inspect variables during development.Customize Without Forking
templates/@EDCBaseAdmin/ (e.g., templates/@EDCBaseAdmin/login.html.twig) to modify default views without extending the bundle.Partial Overrides
{% block %} inheritance to modify onlyHow can I help you explore Laravel packages today?