2lenet/dashboard2-bundle
A Symfony bundle for building customizable dashboards with widgets. Generate widgets via maker, control visibility with roles, configure caching and Twig templates, and store widget data with Doctrine migrations. Includes setup and troubleshooting recipes.
Installation:
composer require 2lenet/dashboard2-bundle
Add to config/routes.yaml:
dashboard_widgets:
resource: "@LleDashboardBundle/Resources/config/routes.yaml"
Run migrations:
php bin/console make:migration
php bin/console doctrine:migrations:migrate
First Widget: Generate a widget via the maker:
php bin/console make:widget
Follow prompts (e.g., MyFirstWidget). This creates:
src/Widget/MyFirstWidget.php) extending AbstractWidget.templates/widget/my_first_widget.html.twig).Render the Dashboard:
Add a route to your routes.yaml:
dashboard:
path: /dashboard
controller: Lle\DashboardBundle\Controller\DashboardController::index
Visit /dashboard to see your widget.
Widget Creation:
make:widget for CRUD widgets or make:workflow-widget for workflow-specific widgets.AbstractWidget if needed (e.g., for custom logic).Rendering:
render() to return HTML (e.g., via twig() helper):
public function render()
{
return $this->twig('widget/my_first_widget.html.twig', [
'data' => $this->fetchData(),
]);
}
widget_class, widget_header).Configuration:
MyWidgetConfigType) and use createForm():
public function render()
{
$form = $this->createForm(MyWidgetConfigType::class);
return $this->twig('widget/my_first_widget.html.twig', [
'config_form' => $form->createView(),
]);
}
getConfig('key').Static Dashboard:
StaticWidgetProviderInterface to define a fixed widget layout:
public function getMyWidgets(): array
{
return [
'stats' => $this->buildWidget(StatsWidget::class, ['title' => 'System Stats']),
];
}
StaticDashboardController::staticDashboard.Chart Integration:
ChartProviderInterface for dynamic charts:
public function getChartList(): array
{
return ['daily_metrics', 'monthly_trends'];
}
public function getChart(string $key): Chart
{
return $this->chartBuilder->createChart(Chart::TYPE_LINE)->setData(...);
}
Dependencies:
symfony/ux-chartjs).dompdf/dompdf is installed.Security:
supports() (e.g., role checks):
public function supports(): bool
{
return $this->security->isGranted('ROLE_ADMIN');
}
Performance:
getCacheKey() and getCacheTimeout():
public function getCacheKey(): string
{
return md5($this->getConfig('cache_dependency'));
}
Testing:
WidgetTypeInterface in unit tests:
$widget = $this->createMock(AbstractWidget::class);
$widget->method('render')->willReturn('<div>Test</div>');
Missing Routes:
dashboard_widgets routes causes 404s. Verify with:
php bin/console debug:router | grep dashboard
Widget Not Appearing:
supports() or verify user roles (e.g., ROLE_DASHBOARD_WIDGET_NAME).php bin/console cache:clear.Static Dashboard Issues:
getWidget() returns the correct instance by static_index.StaticWidgetProvider prevents shared state issues.Twig Template Errors:
@LleDashboard/widget/base_widget.html.twig explicitly. Missing blocks (e.g., widget_class) may break styling.Form Submission:
getConfig().Widget Cache:
0 from getCacheTimeout().public function getCacheKey(): string
{
$key = $this->getId() . "_" . md5($this->config);
error_log("Cache key: $key");
return $key;
}
Static Dashboard:
$provider = new StaticWidgetProvider($widgetTypes);
dump($provider->getMyWidgets());
Custom Widget Types:
AbstractWidget to add shared logic (e.g., BaseDataWidget with fetchData()).Dynamic Roles:
public function supports(): bool
{
return $this->security->isGranted('ROLE_CUSTOM');
}
Asset Management:
asset() in Twig for static assets (e.g., charts). Run php bin/console asset:install if stylesheets are missing.Event Listeners:
WidgetEvent::POST_RENDER) via Symfony’s event dispatcher:
$this->eventDispatcher->dispatch(new WidgetEvent($this, 'post_render'));
Widget Organization:
src/Widget/Admin/, src/Widget/User/).Reusable Components:
widget/base_chart.html.twig).Performance:
getCacheTimeout(86400) (1 day) and invalidate cache on data changes:
$this->cache->delete($this->getCacheKey());
Localization:
messages.en.yaml):
widget.my_first_widget.name: "My First Widget"
How can I help you explore Laravel packages today?