Install the Package:
composer require derafu/renderer derafu/twig
Ensure your composer.json specifies PHP 8.5+:
"require": {
"php": "^8.5",
"derafu/renderer": "^1.0",
"derafu/twig": "^1.0"
}
Publish Configuration:
php artisan vendor:publish --provider="Derafu\Renderer\RendererServiceProvider" --tag="config"
This creates config/renderer.php with default settings.
Register the Service Provider:
Add to config/app.php:
'providers' => [
// ...
Derafu\Renderer\RendererServiceProvider::class,
],
First Render:
Create a Twig template at resources/views/hello.twig:
<h1>Hello, {{ name }}!</h1>
Render it in a controller:
use Derafu\Renderer\Facades\Renderer;
public function show()
{
return Renderer::render('hello', ['name' => 'Laravel']);
}
First Use Case: Use the renderer for non-Blade templates (e.g., PDFs, Markdown emails):
// PDF example (requires mPDF)
$pdfContent = Renderer::render('invoice.pdf.twig', ['user' => $user]);
$pdf = new \Mpdf\Mpdf();
$pdf->WriteHTML($pdfContent);
$pdf->Output('invoice.pdf', 'D');
Template Organization:
Store templates in resources/views/ with extensions indicating format:
.twig → Twig (default).md → Markdown (requires derafu/markdown).pdf.twig → PDF-ready Twig (processed by mPDF)Data Passing: Pass data as associative arrays (supports nested structures):
$data = [
'user' => $user,
'items' => $order->items,
'config' => config('app.settings'),
];
$output = Renderer::render('template.twig', $data);
Format-Specific Patterns:
$pdf = Renderer::renderToPdf('invoice.twig', ['data' => $data]);
$markdown = Renderer::render('email.md', ['data' => $data]);
$html = \Michelf\Markdown::defaultTransform($markdown);
Integration with Laravel:
view('name') with Renderer::render('name.twig') for Twig templates.return response(Renderer::render('email.md', $data), 200, ['Content-Type' => 'text/markdown']);
build() method:
public function build()
{
$body = Renderer::render('emails.welcome.md', ['user' => $this->user]);
return $this->markdown('emails.welcome')->with([
'body' => $body,
]);
}
Caching: Leverage Laravel’s cache for Twig templates:
Renderer::render('template.twig', $data, [
'cache' => true,
'cache_key' => 'template_' . md5(serialize($data)),
]);
Error Handling: Wrap renders in try-catch for graceful degradation:
try {
$output = Renderer::render('template.twig', $data);
} catch (\Derafu\Renderer\Exceptions\TemplateNotFoundException $e) {
return response('Template not found', 500);
}
Service Provider Customization: Extend the default provider to add engines or modify behavior:
// app/Providers/RendererServiceProvider.php
public function register()
{
$this->app->singleton('renderer', function ($app) {
$renderer = new \Derafu\Renderer\Renderer([
'twig' => new \Derafu\Twig\TwigEngine($app['path.base']),
'blade' => $app['view'], // Optional: Fallback to Blade
]);
$renderer->addEngine('md', new \Derafu\Markdown\MarkdownEngine());
return $renderer;
});
}
Facade Aliases:
Add custom aliases in config/app.php:
'aliases' => [
// ...
'Renderer' => \Derafu\Renderer\Facades\Renderer::class,
'PdfRenderer' => \Derafu\Renderer\Facades\PdfRenderer::class, // Custom facade
],
Artisan Commands: Create a custom command to validate templates:
php artisan renderer:validate resources/views
Testing: Use Laravel’s testing helpers with the renderer:
public function testRenderer()
{
$this->app->make('renderer')->shouldReceive('render')
->once()
->with('template.twig', ['data' => 'test'])
->andReturn('<html>...</html>');
}
Livewire/Alpine Integration: For Twig templates used with Livewire, ensure Alpine.js/CDN inclusion:
{# resources/views/hello.twig #}
@extends('layouts.app')
@section('scripts')
@vite(['resources/js/app.js'])
<script src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
@endsection
Twig vs. Blade Syntax:
{{ }} for output and {% %} for logic, while Blade uses @{{ }} and @if. Mixing them without a bridge causes errors.Template Paths:
resources/views/ but may not auto-discover subdirectories like Laravel’s View facade.'paths' => [
resource_path('views'),
resource_path('views/emails'),
resource_path('views/pdf'),
],
PDF Generation:
<html>, <body> tags).{# resources/views/pdf/base.twig #}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body { font-family: Arial; }
</style>
</head>
<body>
{{ block('content') }}
</body>
</html>
Caching Quirks:
storage/framework/views) may conflict with Laravel’s view cache.'twig' => [
'cache' => storage_path('framework/views/twig'),
],
Markdown Parsing:
derafu/markdown engine may not support all Markdown features (e.g., tables, footnotes).michelf/php-markdown for complex cases:
$markdown = Renderer::render('email.md', $data);
$html = \Michelf\Markdown::defaultTransform($markdown);
Dependency Conflicts:
derafu/twig may pull in older versions of twig/twig or symfony/dependency-injection, causing conflicts.composer.json:
"require": {
"twig/twig": "^3.4",
"symfony/dependency-injection": "^6.0"
}
config/renderer.php:
'twig' => [
'debug'
How can I help you explore Laravel packages today?