Installation
composer require bbit/admin-bundle
Register the bundle in AppKernel.php:
new BBIT\AdminBundle\BBITAdminBundle(),
new BBIT\DataGridBundle\BBITDataGridBundle(),
new Knp\Bundle\PaginatorBundle\KnpPaginatorBundle(),
new Knp\Bundle\MenuBundle\KnpMenuBundle(),
new Symfony\Bundle\AsseticBundle\AsseticBundle()
First Admin Class
Create a basic ItemAdmin extending BaseAdmin in src/AppBundle/Admin/ItemAdmin.php:
namespace AppBundle\Admin;
use BBIT\AdminBundle\Admin\BaseAdmin;
use BBIT\DataGridBundle\Service\DataGridService;
use Symfony\Component\Form\FormBuilder;
class ItemAdmin extends BaseAdmin
{
protected function mapListFields(DataGridService $grid) {
$grid->addField('id', 'string');
$grid->addField('name', 'string');
}
protected function mapFormFields(FormBuilder $formBuilder) {
$formBuilder->add('name');
}
}
Register Admin Service
Define the admin service in app/config/services.yml:
services:
item_admin:
class: AppBundle\Admin\ItemAdmin
arguments: ['AppBundle\Entity\Item']
tags:
- { name: bbit.admin, label: 'Items', icon: 'fa fa-tag' }
Access Admin Panel
Visit /admin (or your configured route_prefix) to see the auto-generated CRUD interface for Item.
CRUD Operations
Extend BaseAdmin and override:
mapListFields() → Configure DataGrid columns.mapFormFields() → Define form fields.listQueryBuilder() → Customize list queries (e.g., joins, where clauses).prePersist()/preUpdate() → Modify entities before save.Example: Filtering and sorting
protected function listQueryBuilder() {
$qb = parent::listQueryBuilder();
$qb->andWhere('e.active = :active')->setParameter('active', true);
return $qb;
}
Form Customization
Use Symfony’s FormBuilder methods:
protected function mapFormFields(FormBuilder $formBuilder) {
$formBuilder
->add('name', TextType::class, ['label' => 'Item Name'])
->add('price', MoneyType::class)
->add('tags', EntityType::class, ['class' => 'AppBundle:Tag']);
}
DataGrid Enhancements
Leverage DataGridService for advanced features:
protected function mapListFields(DataGridService $grid) {
$grid->addField('createdAt', 'datetime', [
'label' => 'Created',
'format' => 'Y-m-d H:i',
]);
$grid->addAction('edit', 'Edit', 'fa fa-edit');
$grid->addAction('delete', 'Delete', 'fa fa-trash', ['confirm' => true]);
}
Bulk Actions
Add bulk operations via mapBulkActions():
protected function mapBulkActions() {
return [
'delete' => [
'label' => 'Delete Selected',
'icon' => 'fa fa-trash',
'route' => 'admin_item_bulk_delete',
'method' => 'POST',
],
];
}
Integration with Other Bundles
bbit.admin tag.templates/BBITAdminBundle/ to customize.getEntityManager() in your admin class.Dynamic Admin Classes Use dependency injection to load admin classes dynamically:
# services.yml
app.admin.item:
class: AppBundle\Admin\DynamicItemAdmin
arguments: ['%app.dynamic_entity_class%']
tags: [{ name: bbit.admin, label: 'Dynamic Items' }]
Role-Based Access Control (RBAC)
Override isGranted() to restrict actions:
public function isGranted($attribute, $object = null) {
if ($attribute === 'edit' && !$this->getUser()->hasRole('ROLE_ADMIN')) {
return false;
}
return parent::isGranted($attribute, $object);
}
Custom Routes
Define custom routes in routing.yml:
admin_item_export:
path: /items/export
defaults: { _controller: 'AppBundle:Admin/ItemAdmin::exportAction' }
Then implement exportAction() in your admin class.
Event Listeners
Attach listeners to admin events (e.g., prePersist, postDelete):
$dispatcher->addListener('bbit.admin.pre_persist', function ($event) {
$entity = $event->getEntity();
$entity->setUpdatedBy($event->getUser());
});
Entity Manager Injection
EntityManager can cause listQueryBuilder() to fail.BaseAdmin and call parent::listQueryBuilder() to ensure proper EM injection.$this->getEntityManager() in custom queries.Routing Conflicts
_admin_item_custom).DataGrid Caching
config.yml:
knp_paginator:
page_range: 5
default_options:
page_name: page
sort_field_name: sort
sort_direction_name: direction
distinct: true
Form Type Overrides
Asset Loading
BBITAdminBundle:Admin:layout.html.twig) and add assets via {% block stylesheets %} or {% block javascripts %}.Enable Debug Mode
Set APP_DEBUG=true in .env to see detailed errors and template inheritance.
Log Admin Events
Enable monolog for bbit.admin events:
# config.yml
monolog:
handlers:
admin:
type: stream
path: "%kernel.logs_dir%/admin.log"
level: debug
channels: ["bbit.admin"]
Check DataGrid Queries Use Doctrine’s query logging to debug slow queries:
// config.yml
doctrine:
dbal:
logging: true
profiling: true
Template Debugging
Use Twig’s dump() or var_export() to inspect variables:
{{ dump(grid) }}
Custom Templates
Override any template in templates/BBITAdminBundle/Admin/ (e.g., list.html.twig, form.html.twig).
Admin Events Listen to built-in events:
bbit.admin.pre_list (modify list query)bbit.admin.post_persist (post-save logic)bbit.admin.pre_delete (pre-delete validation)Example listener:
$dispatcher->addListener('bbit.admin.pre_delete', function ($event) {
if (!$event->getUser()->hasRole('ROLE_SUPER_ADMIN')) {
throw new \RuntimeException('Unauthorized');
}
});
Dynamic Field Mapping Use closures for dynamic field mapping:
protected function mapListFields(DataGridService $grid) {
$grid->addField('price', 'currency', function ($field) {
$field->setCurrency('USD');
});
}
API Integration
Extend the bundle to support API responses by overriding getResponse() in your admin class.
route_prefix
/admin. Change it in config.yml:
bbit_admin:
How can I help you explore Laravel packages today?