Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Blade Laravel Package

philo/laravel-blade

Use Laravel's Blade template engine outside of Laravel. This package compiles .blade.php templates into plain PHP through a simple standalone API, supporting layouts, includes, directives, and caching—ideal for lightweight projects that want Blade's clean syntax without the full framework.

View on GitHub
Deep Wiki
Context7

Getting Started

philo/laravel-blade lets you render Blade templates without booting a full Laravel application. It wraps the illuminate/view internals (FileViewFinder, BladeCompiler, Factory) behind a tiny bootstrap class.

Install

composer require philo/laravel-blade

The last tagged release is from December 2015 and pins illuminate/* to the Laravel 5.1/5.2 line. On modern PHP you will likely need --ignore-platform-reqs and should assume you are working in a legacy context (see Gotchas).

Two directories, then one object

You need a views directory and a pre-existing, writable cache directory. The package does not create them for you.

use Philo\Blade\Blade;

$blade = new Blade(__DIR__.'/views', __DIR__.'/cache');

echo $blade->view()->make('emails.welcome', ['name' => 'Taylor'])->render();

First use case — transactional email, PDF invoice, or notification body rendered from a queue worker, CLI script, or microservice, where the template needs @extends, @include, and {{ }} escaping but not the whole framework. That is where this package earns its keep.

Where to look first — the bootstrap class itself (src/Philo/Blade/Blade.php, roughly 100 lines). It wires Filesystem → EngineResolver → FileViewFinder → BladeCompiler → Factory and exposes that factory through view(). Reading it once tells you exactly what is and isn't available, which is most of the learning curve. After that, the standard illuminate/view docs apply verbatim.

Implementation Patterns

Register it once, as a singleton. Constructing Blade per render rebuilds the compiler and re-stats every template file. Bind it in your container (Lumen, Slim, custom PSR-11) and inject it.

$container->singleton(Blade::class, fn() => new Blade(
    config('views.path'),
    config('views.cache')
));

Layouts and partials behave normally. Everything under the view path is addressable with dot notation, and inheritance works as it does in Laravel:

{{-- views/layouts/app.blade.php --}}
<html><body>@yield('content')</body></html>

{{-- views/pages/about.blade.php --}}
@extends('layouts.app')
@section('content')
  @include('partials.header', ['title' => 'About'])
  <p>Hello {{ $name }}</p>
@endsection

Share global data instead of threading it through every call. App name, base URL, current user — anything present in every template.

$blade->view()->share('appName', 'Acme');
$blade->view()->share('user', $user);

Custom directives are the main extension point for replacing Laravel helpers you no longer have:

$blade->compiler()->directive('money', function ($expression) {
    return "<?php echo number_format({$expression}, 2); ?>";
});

// @money($invoice->total)  →  1,234.00

View composers keep controllers thin when a partial always needs the same data:

$blade->view()->composer('partials.nav', function ($view) {
    $view->with('links', Navigation::all());
});

Namespaced paths are useful for theming or multi-tenant setups where each tenant ships its own view root:

$blade->view()->addNamespace('tenant', storage_path("tenants/{$id}/views"));
echo $blade->view()->make('tenant::dashboard')->render();

String templates (previews, stored snippets, admin-editable snippets):

echo $blade->render('Hello {{ $name }}', ['name' => 'Taylor']);

Use compiler()->compileString() only when you genuinely want the generated PHP; for output, render() is the correct call.

Testing. Point the cache at a per-test temp directory and assert on the rendered string. Cached artifacts otherwise bleed across tests and produce confusing "my edit didn't apply" failures.

protected function setUp(): void {
    $this->cache = sys_get_temp_dir().'/blade-'.uniqid();
    mkdir($this->cache);
    $this->blade = new Blade(__DIR__.'/fixtures/views', $this->cache);
}

Deployment. Flush the cache directory as part of your release step. There is no view:clear; a find cache -type f -delete (or a small precompile script that renders every template once) is the equivalent.

Gotchas and Tips

This package is effectively abandoned. Last release 2015-12-04, no dependents in the ecosystem, and its illuminate/* constraints are from the 5.1/5.2 era. On PHP 8 you will hit removed functions (each()), removed string helpers, dynamic-property deprecations, and Composer platform conflicts. For greenfield work choose jenssegers/blade (maintained, tracks modern Illuminate) or eftec/bladeone (zero dependencies, single library). Adopt this one only to service code already depending on it.

The cache directory must exist and be writable. A missing directory surfaces as an obscure Filesystem::put failure rather than a helpful "cache not writable" message. Create it in your bootstrap.

No Laravel globals exist. route(), asset(), csrf_field(), config(), old(), @auth, @can, @lang, @error, @component, @slot, and @once are all unavailable — several postdate this package's compiler entirely. Provide replacements as directives or closures in the shared data. If you migrate to a modern Blade, every one of these becomes a silent runtime error, so centralize your shims.

Template rendering is code execution. Blade compiles to raw PHP. {{ }} is escaped; {!! !!}, @php, and @include of arbitrary paths are not. Never pass user-authored or user-uploaded templates to render(). If you must support tenant templates, run compilation in an isolated process with a directive whitelist and a filesystem jail.

Escape helper dependency. {{ }} calls the global e() function supplied by illuminate/support. If you pin, upgrade, or replace that package independently, you get Call to undefined function e() in every template. Keep the Illuminate versions locked together.

@extends must be the first token in the file. Any leading whitespace or BOM is emitted as literal output before the layout, which typically manifests as a blank line above <!DOCTYPE html> and mystifying header-already-sent errors.

Watch the Blade syntax vintage. This compiler predates the null-coalescing operator and the {{ $var ?? 'default' }} form; the older {{ $var or 'default' }} idiom is what it understands. Copy-pasting modern Blade snippets will compile to broken PHP.

Debug by reading the compiled file. Compiled output lands in the cache directory, keyed by a hash of the view path. When a template throws something unhelpful, open the corresponding compiled PHP — it is the fastest way to see what a directive actually produced.

Stale cache after moving view paths. The compiled filename derives from the view path. Changing the path in config leaves the old artifacts behind, and you can end up debugging a template that is no longer the one being executed. Flush on any path change.

Long-running processes leak shared state. view()->share() and composers mutate the factory permanently. In a queue daemon or Swoole/Octane-style worker, data shared for job A is still visible in job B. Reset shares between jobs or construct a fresh Blade per unit of work.

Directive closures receive the raw argument string, parentheses included. Handle both @datetime($x) and bare @datetime, or you will emit datetime($x) calls where you expected datetime().

Inside a template, $this is the View object, not your controller or service. Do not call application methods off it — pass what you need through the data array.

Events may be a no-op. The bootstrap does not always register an event dispatcher, so anything in illuminate/view that fires events (composer hooks in some configurations, certain include behaviors) can silently do nothing. If a composer never runs, this is why — construct the Factory with a dispatcher yourself or invoke the callback directly.

Performance ceiling. Every render stats the template for mtime. For high-volume rendering, precompile and include the generated PHP directly, or cache the final HTML string keyed on data hash plus template mtime.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console