creative-web-solution/svg-chart-bundle
Symfony bundle to generate SVG charts (pie/donut and line) using meyfa/php-svg. Create charts from JSON-configured data and styles, including legend labels, slice colors, donut thickness, line connectors, dimensions, and offsets; returns SVG responses.
Installation:
composer require creative-web-solution/svg-chart-bundle
Ensure meyfa/php-svg is installed as a dependency.
First Use Case:
Create a JSON config file (e.g., pie_chart_data.json) with minimal data:
{
"data": [{
"values": [{
"value": 0.5,
"color": "#ff0000",
"label": "50%"
}]
}],
"styles": {
"mode": "pie",
"width": 300,
"height": 200
}
}
Generate the chart in a controller:
use Cws\Bundle\SVGChartBundle\SVGChart\SVGChart;
use Symfony\Component\HttpFoundation\Response;
public function showChart()
{
$config = json_decode(file_get_contents('pie_chart_data.json'));
$svg = SVGChart::createPie($config->data[0], $config->styles);
return new Response($svg, 200, ['Content-Type' => 'image/svg+xml']);
}
Quick Integration:
/chart/pie).<img src="{{ path('chart_route') }}" />.Dynamic Data Binding: Fetch data from a database or API and transform it into the required JSON structure:
$chartData = $entityManager->getRepository(YourEntity::class)
->findBy([], ['value' => 'DESC'])
->map(fn($item) => [
'value' => $item->getPercentage(),
'color' => $item->getColor(),
'label' => $item->getLabel()
]);
Reusable Config Classes:
Create a ChartConfig class to encapsulate JSON logic:
class PieChartConfig
{
public static function fromEntity(YourEntity $entity): array
{
return [
'data' => [['values' => self::mapEntityToValues($entity)]],
'styles' => self::defaultStyles()
];
}
}
Controller Layer:
public function generateLineChart(LineData $lineData)
{
$config = LineChartConfig::fromData($lineData);
$svg = SVGChart::createLines($config['data'], $config['styles']);
return new Response($svg, 200, ['Content-Type' => 'image/svg+xml']);
}
Service Layer: Extract chart generation to a service for reusability:
class ChartService
{
public function generatePieChart(array $data, array $styles): string
{
return SVGChart::createPie($data, $styles);
}
}
Caching: Cache generated SVGs to reduce load:
$cacheKey = 'chart_' . md5(serialize($config));
if (!$svg = $cache->get($cacheKey)) {
$svg = SVGChart::createPie($config['data'], $config['styles']);
$cache->set($cacheKey, $svg, 3600); // Cache for 1 hour
}
Twig Extensions: Create a Twig extension to render charts directly in templates:
class ChartExtension extends \Twig\Extension\AbstractExtension
{
public function getFunctions()
{
return [
new \Twig\TwigFunction('svg_pie_chart', [$this, 'renderPieChart']),
];
}
public function renderPieChart(array $data, array $styles)
{
return SVGChart::createPie($data, $styles);
}
}
Usage in Twig:
<img src="data:image/svg+xml;base64,{{ svg_pie_chart(data, styles)|base64_encode }}" />
Event Listeners: Generate charts on entity events (e.g., post-save):
public function onEntitySave(YourEntity $entity)
{
$config = PieChartConfig::fromEntity($entity);
$svg = SVGChart::createPie($config['data'], $config['styles']);
$entity->setChartData($svg);
$entityManager->flush();
}
API Responses: Return SVGs as API responses:
return $this->json([
'chart' => base64_encode(SVGChart::createBars($data, $styles))
], 200, [], ['Content-Type' => 'application/json']);
JSON Validation:
values, styles) will throw errors.json_last_error() before passing to SVGChart:
$json = file_get_contents('chart_data.json');
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \RuntimeException('Invalid JSON: ' . json_last_error_msg());
}
SVG Content-Type:
Content-Type: image/svg+xml will corrupt the SVG output.private function svgResponse(string $svg): Response
{
return new Response($svg, 200, ['Content-Type' => 'image/svg+xml']);
}
Data Array Indexing:
data is processed. Extra elements are ignored.data are processed. Ensure correct ordering.CSS Class Conflicts:
cssClass or cssSliceClass may conflict with global styles. Use unique prefixes (e.g., chart-pie-2023).Donut vs. Pie Mode:
donutThickness and donutMainLegend are ignored in pie mode. Set "mode": "donut" explicitly.Label Rendering:
<span>€</span>) may break if not escaped. Use htmlspecialchars or configure textTemplate carefully.Inspect Generated SVG: Save the SVG output to a file and open it in a browser to validate:
file_put_contents('debug_chart.svg', $svg);
Log Config:
Log the $config array before passing to SVGChart to verify structure:
\Monolog\Logger::getInstance('app')->info('Chart config:', $config);
Dependency Conflicts:
meyfa/php-svg is compatible with your PHP version (e.g., PHP 8.x may require a fork or patch).Custom Chart Types:
Extend the bundle by creating a new class (e.g., SVGChart::createRadar()) and replicate the logic from existing methods.
Dynamic Styling: Override styles dynamically based on user preferences:
$styles['cssClass'] .= ' user-' . $user->getTheme();
Interactive Charts: Use JavaScript libraries (e.g., D3.js) to overlay interactivity on the static SVG output.
Theming: Create a theme service to generate consistent styles:
class ChartTheme
{
public function getPieStyles(string $themeColor): array
{
return [
'cssClass' => 'theme-' . $themeColor,
'radius' => 120,
'colors' => ['#' . $themeColor, '#cccccc']
];
}
}
Localization: Localize axis labels or legends by replacing static strings in the JSON config:
"labels": [
{"label": "{{ 'Jan.'|trans }}"},
{"label": "{{ 'Feb.'|trans }}"}
]
How can I help you explore Laravel packages today?