meyfa/php-svg
Lightweight PHP library to create, read, and manipulate SVGs. Build SVG documents programmatically, edit shapes and attributes via a DOM-like API, and export clean SVG/XML. Handy for generating icons, diagrams, and server-side graphics without external dependencies.
## Getting Started
### Minimal Steps
1. **Installation**
```bash
composer require meyfa/php-svg
Note: Ensure your project uses PHP 8.4 for full compatibility with v0.16.1.
First Use Case: Basic SVG Creation
use Meyfa\Svg\Svg;
$svg = new Svg();
$svg->setViewBox('0 0 200 200');
$svg->addElement('rect', [
'x' => 20,
'y' => 20,
'width' => 160,
'height' => 160,
'fill' => '#3498db',
'stroke' => '#2980b9',
'stroke-width' => 2
]);
echo $svg->render();
Outputs a centered blue rectangle with a border.
Where to Look First
Meyfa\Svg\Svg (main container) and Meyfa\Svg\SvgElement (individual elements).Dynamic SVG Generation from Data
function generateUserBadge(string $name, string $color): string {
$svg = new Svg();
$svg->setViewBox('0 0 120 80');
$svg->addElement('rect', [
'width' => '100%',
'height' => '100%',
'fill' => $color,
'rx' => 10
]);
$svg->addElement('text', [
'x' => 60,
'y' => 45,
'text-anchor' => 'middle',
'font-size' => '16px',
'fill' => '#fff'
], $name);
return $svg->render();
}
Modifying Existing SVGs
$svgContent = file_get_contents('existing.svg');
$svg = Svg::loadFromString($svgContent);
$svg->addElement('circle', [
'cx' => 50,
'cy' => 50,
'r' => 20,
'fill' => 'red'
]);
file_put_contents('modified.svg', $svg->render());
Laravel Facade Integration
// In AppServiceProvider (PHP 8.4 compatible)
public function register(): void {
$this->app->bind('svg', fn() => new \Meyfa\Svg\Svg());
}
// Usage in controllers
$svg = app('svg');
$svg->addElement('path', [...]);
return response($svg->render(), 200)
->header('Content-Type', 'image/svg+xml');
Queue-Based Generation for Heavy SVGs
// Job class (PHP 8.4 compatible)
class GenerateComplexSvgJob implements ShouldQueue {
public function handle(): void {
$svg = new Svg();
// Complex generation logic...
Storage::put('complex.svg', $svg->render());
}
}
// Dispatch from controller
GenerateComplexSvgJob::dispatch();
Blade Directives for Templating
// In AppServiceProvider (PHP 8.4 compatible)
Blade::directive('svg', function ($expression) {
return "<?php echo app('svg')->{$expression}; ?>";
});
// In Blade template
@svg('addElement("rect", ["width" => "100%", "height" => "100%", "fill" => "#f0f0f0"])')
$svg = Cache::remember("svg-badge-{$userId}", now()->addHours(1), function() use ($user) {
return generateUserBadge($user->name, $user->color);
});
Storage::disk('public')->put("avatars/{$userId}.svg", $svg->render());
return response($svg->render(), 200)
->header('Content-Type', 'image/svg+xml');
$svg = Mockery::mock(Svg::class);
$svg->shouldReceive('render')->andReturn('<svg>...</svg>');
PHP 8.4 Deprecations
foreach with string keys, create_function).Attribute Case Sensitivity
fill not Fill).$attrs = array_change_key_case($attrs, CASE_LOWER);
$svg->addElement('rect', $attrs);
Namespace Issues
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" ...>
$svg = Svg::loadFromString($content, 'http://www.w3.org/2000/svg');
Performance with Complex Paths
XSS Vulnerabilities
$text = htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
$svg->addElement('text', [...], $text);
Validate SVG Output Use the W3C Validator to check for malformed SVGs.
Inspect DOM Structure
echo $svg->render(); // Check raw output
Or use a DOM inspector in your browser to debug rendered SVGs.
Enable Error Reporting (PHP 8.4)
libxml_use_internal_errors(true);
$svg = Svg::loadFromString($content);
$errors = libxml_get_errors();
if (!empty($errors)) {
foreach ($errors as $error) {
error_log("SVG Error: {$error->message}");
}
libxml_clear_errors();
}
Default XML Declaration
The package may not include <?xml ...?> by default. Add it manually if needed:
$svg->setXmlDeclaration('1.0', 'UTF-8');
Namespace Handling If working with SVG 2.0 features, ensure the namespace is set:
$svg->setNamespace('http://www.w3.org/2000/svg');
Attribute Ordering
SVG parsers may ignore or reorder attributes. Explicitly set critical ones (e.g., viewBox) first.
Custom Element Types Extend the library to support domain-specific elements:
class CustomSvg extends Svg {
public function addChart(array $data): void {
// Custom logic for charts
}
}
Event Hooks Add pre/post-render hooks for logging or validation (PHP 8.4 compatible):
$svg = new Svg();
$svg->on('render', function(Svg $svg) {
error_log("Rendering SVG with " . $svg->countElements() . " elements");
});
Integration with Laravel Nova Create a custom SVG field for Nova:
use Laravel\Nova\Fields\Field;
class SvgField extends Field {
public function render($value): string
How can I help you explore Laravel packages today?