Installation
Add the bundle to your composer.json:
composer require egb/reports-bundle
Register the bundle in config/bundles.php (Symfony 4+):
return [
// ...
Egb\ReportsBundle\EgbReportsBundle::class => ['all' => true],
];
First Report
Define a report class (e.g., src/Report/UserReport.php):
namespace App\Report;
use Egb\ReportsBundle\Report\AbstractReport;
class UserReport extends AbstractReport
{
protected $title = 'User Activity Report';
protected $columns = [
'id' => 'ID',
'name' => 'Name',
'email' => 'Email',
];
protected $data = []; // Populate via query builder or array
public function getData()
{
return $this->data;
}
}
Route & Controller
// routes.yaml
reports_user:
path: /reports/user
controller: App\Controller\ReportController::userReport
// src/Controller/ReportController.php
use Egb\ReportsBundle\Report\ReportManager;
class ReportController
{
public function userReport(ReportManager $reportManager)
{
$report = new UserReport();
$report->setData(User::all()->toArray()); // Example data source
return $reportManager->render($report);
}
}
View Template
Create a Twig template (templates/reports/user_report.html.twig):
{% extends 'EgbReportsBundle::report.html.twig' %}
{% block report_title %}{{ report.title }}{% endblock %}
Query Builder Integration
Use Eloquent or Doctrine queries to populate $data:
$report->setData(User::where('active', true)->get()->toArray());
Dynamic Columns
Define columns dynamically in buildColumns():
protected function buildColumns()
{
return [
'created_at' => 'Registration Date',
'role' => 'Role',
];
}
Export Formats
Leverage the ReportManager for CSV/Excel exports:
$reportManager->export($report, 'csv');
Custom Styling Override Twig blocks in your template:
{% block report_header %}
<h1>{{ report.title }} ({{ report.data|length }} records)</h1>
{% endblock %}
Conditional Rendering Use Twig logic to hide/show columns:
{% if report.showColumn('email') %}
<th>{{ report.getColumnTitle('email') }}</th>
{% endif %}
Multi-Source Reports Merge data from multiple queries:
$report->setData([
'users' => User::all()->toArray(),
'stats' => Stat::whereYear('created_at', date('Y'))->get()->toArray(),
]);
Parameterized Reports Inject parameters via constructor:
class UserReport extends AbstractReport
{
public function __construct($startDate, $endDate)
{
$this->startDate = $startDate;
$this->endDate = $endDate;
}
public function getData()
{
return User::whereBetween('created_at', [$this->startDate, $this->endDate])
->get()
->toArray();
}
}
API-Driven Reports Return JSON for frontend consumption:
return $reportManager->toArray($report);
Data Structure Requirements
$data to be an array of associative arrays.toArray() on Eloquent collections or ensure Doctrine entities are hydrated to arrays.Column Name Mismatches
$columns keys don’t match array keys in $data, columns will render empty.getColumnTitle() with fallback:
{{ report.getColumnTitle('non_existent', 'N/A') }}
Caching Headaches
now()) may not refresh.cache:clear after updates.Twig Template Overrides
EgbReportsBundle::report.html.twig will break rendering.{% extends 'EgbReportsBundle::report.html.twig' %} as the first line.Inspect Report Data Dump the report object in the controller:
dd($reportManager->toArray($report));
Check Column Definitions
Verify $columns in your report class matches the data structure:
// Debug column keys
$this->columns = array_flip(array_keys($this->data[0] ?? []));
Export Issues
league/csv or phpoffice/phpexcel packages are installed.composer require league/csv or composer require phpoffice/phpexcel.Custom Report Types
Extend AbstractReport to add methods like formatValue():
protected function formatValue($key, $value)
{
if ($key === 'created_at') {
return (new \DateTime($value))->format('Y-m-d H:i');
}
return $value;
}
Override Rendering Logic Replace the Twig template entirely by injecting a custom renderer:
# config/packages/egb_reports.yaml
egb_reports:
renderer: 'App\Renderer\CustomReportRenderer'
Add Actions to Rows Include action buttons/links in the report:
{% for row in report.data %}
<tr>
{% for column in report.columns %}
<td>{{ row[column] }}</td>
{% endfor %}
<td>
<a href="{{ path('user_edit', {'id': row.id}) }}">Edit</a>
</td>
</tr>
{% endfor %}
Default Export Format
Set the default export format in config/packages/egb_reports.yaml:
egb_reports:
default_export: 'csv' # or 'excel'
Disable Pagination If using large datasets, disable pagination in the Twig template:
{% set pagination = false %}
{% include 'EgbReportsBundle::report.html.twig' %}
Localization Translate column titles via translation files:
# messages.en.yaml
reports.columns.id: 'User ID'
reports.columns.name: 'Full Name'
Then reference in the report:
protected $columns = [
'id' => 'reports.columns.id',
'name' => 'reports.columns.name',
];
How can I help you explore Laravel packages today?