Add Blade template engine support
Summary
Add BladeAdapter as a second view engine alongside Twig. The adapter pattern introduced in refactor/views makes this straightforward — Blade is just another adapter that consumes _helpers, _directives and _shared from the View Factory.
Background
illuminate/view (already a dependency) ships Blade out of the box. The ViewServiceProvider now orchestrates engine-agnostic extensions via AbstractViewExtension — BladeAdapter just needs to map these to Blade's equivalents.
What needs to be done
BladeAdapter — src/View/Engines/Blade/BladeAdapter.php
Implements ViewAdapterInterface:
public function register(Application $app): void
{
// BladeCompiler with cache path
$app->singleton('blade.compiler', fn($c) => new BladeCompiler(
$c['files'],
$c['path.cache'] . '/Blade',
));
}
public function boot(Factory $view, Application $app): void
{
$blade = $app['blade.compiler'];
// _helpers → {{ helper($value) }}
foreach ($view->getShared()['_helpers'] ?? [] as $name => $callable) {
$blade->directive($name, fn($expr) => "<?php echo {$name}({$expr}); ?>");
}
// _directives → @directive
foreach ($view->getShared()['_directives'] ?? [] as $name => $callable) {
$blade->directive($name, fn($expr) => "<?php {$name}({$expr}); ?>");
}
// Register .blade.php as a view engine
$view->addExtension(
'blade.php',
'blade',
fn() => new CompilerEngine($blade, $app['files']),
);
// Shared variables available in Blade via View::share() automatically
}
Add to ViewServiceProvider::$adapters
protected array $adapters = [
TwigAdapter::class,
BladeAdapter::class, // 🆕
];
TemplateServiceProvider — Brain Hierarchy already supports both
$finder = new ByFolders($layoutPaths, 'twig', 'blade.php');
Already done in refactor/views — no changes needed.
Tests
BladeAdapterTest — registers blade.compiler, registers .blade.php extension
- Integration test —
.blade.php template renders correctly
- Coexistence test —
.twig and .blade.php can coexist in same project
Notes
illuminate/view already includes BladeCompiler and CompilerEngine — no new dependencies
_helpers mapping to Blade is slightly different from Twig (no pipe syntax) — document in views.md
fn global is Twig-only — no Blade equivalent needed (call PHP directly in Blade)
getGlobals() equivalent in Blade is View::share() — already handled via share() in AbstractViewExtension
Acceptance criteria
Add Blade template engine support
Summary
Add
BladeAdapteras a second view engine alongside Twig. The adapter pattern introduced inrefactor/viewsmakes this straightforward — Blade is just another adapter that consumes_helpers,_directivesand_sharedfrom the View Factory.Background
illuminate/view(already a dependency) ships Blade out of the box. TheViewServiceProvidernow orchestrates engine-agnostic extensions viaAbstractViewExtension—BladeAdapterjust needs to map these to Blade's equivalents.What needs to be done
BladeAdapter—src/View/Engines/Blade/BladeAdapter.phpImplements
ViewAdapterInterface:Add to
ViewServiceProvider::$adaptersTemplateServiceProvider— Brain Hierarchy already supports bothAlready done in
refactor/views— no changes needed.Tests
BladeAdapterTest— registers blade.compiler, registers .blade.php extension.blade.phptemplate renders correctly.twigand.blade.phpcan coexist in same projectNotes
illuminate/viewalready includesBladeCompilerandCompilerEngine— no new dependencies_helpersmapping to Blade is slightly different from Twig (no pipe syntax) — document inviews.mdfnglobal is Twig-only — no Blade equivalent needed (call PHP directly in Blade)getGlobals()equivalent in Blade isView::share()— already handled viashare()inAbstractViewExtensionAcceptance criteria
.blade.phptemplates render in the Layout directoryAbstractViewExtensionavailable in Blade as{{ helper($value) }}AbstractViewExtensionavailable as@directiveshare()available in Blade templatesviews.mdupdated with Blade examples