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

Simple View Engine Laravel Package

crodas/simple-view-engine

A simple, fast PHP view engine with a lightweight template syntax. It compiles templates to plain PHP for speed, supports template inheritance and output escaping, and drops into existing PHP projects without heavy dependencies or framework lock-in.

View on GitHub
Deep Wiki
Context7

Getting Started

What it is: a framework-agnostic, standalone port of Laravel 4's Blade compiler. It parses @directive / {{ }} templates and compiles them to plain PHP files you include. It is not a Laravel view layer — no service provider, no facade, no view() helper, no shared-data bag. It is a template → PHP compiler you wire up yourself.

Install and orient yourself

composer require crodas/simple-view-engine

First files to read, in this order:

  1. README.md — the entire public API is 2–3 methods; read it end to end.
  2. src/…/SimpleView.php — the render/driver class; note the constructor arguments (cache/compile directory vs. template directory) and the exact render() signature before writing anything.
  3. The compiler class — this is your reference for which directives actually exist.
  4. tests/ — the most reliable documentation of directive semantics, especially escaping.

Minimal end-to-end use

require __DIR__ . '/vendor/autoload.php';

$view = new SimpleView\SimpleView(__DIR__ . '/cache');   // compile target; must be writable
echo $view->render(__DIR__ . '/views/greeting.php', [
    'name' => 'Ada',
    'items' => ['a', 'b', 'c'],
]);
{{-- views/greeting.php --}}
@foreach ($items as $item)
  <li>{{ $item }}</li>
@endforeach
Hello, {{{ $name }}}.

Your first real use case: it is a code generator, not a page-renderer. Reach for it when you have a small CLI/build task that emits repetitive files — model/repository scaffolding, migration stubs, config bundles, Dockerfiles, email bodies, static HTML — and you want @foreach + @if + layout inheritance instead of string concatenation and sprintf. Treat "generate 40 files from one template + one data array" as the target workload; that is where the compile-once-then-include model pays off and where its thin feature set is not a liability.

Implementation Patterns

Two-phase render (compile, then include). The cheapest way to use this package at scale is to separate compilation from execution: compile every template once during your build/deploy step, commit or ship the resulting PHP files, and let production only include them. Cache the renderer instance if you are looping over many templates in one process — re-instantiating per file throws away any internal state.

Layout inheritance is the whole point. Write one layout.php with @yield('content') and @yield('title'), then have each generated file start with:

@extends('layout')
@section('title')
    {{ $module }} module
@stop
@section('content')
    class {{ $module }} extends Model { ... }
@stop

For a code generator this is what keeps 40 emitted files consistent. @include for reusable fragments (e.g. a phpdoc.php block), remembering includes resolve against the view root, not the including file.

Data as a plain array, and shape it deliberately. Build one associative array per file and pass it whole. Because data is extracted into the template's local scope, keep keys in snake_case or a namespace-ish prefix ($module, $module_fields) so they cannot collide with loop variables or $this. Pre-compute anything non-trivial in PHP — formatted dates, pluralised names, indentation strings — and hand the template finished values. Do not put business logic in templates; you will debug it through a compiled PHP file.

Wrap it in a thin service of your own. Given the package's zero adoption, do not scatter new SimpleView(...) calls through your codebase. Create one ViewFactory/Renderer class that owns the instance, the template root, the cache root, and a render(string $template, array $data): string method. That single seam lets you swap engines, add escaping policy, add shared/global data (which the package lacks), and test generators without touching templates.

Dev vs. prod workflow. In development, delete the compile directory (or wrap compilation in a filemtime check you control) so edits to .php templates are picked up. In CI, add a job that compiles all templates and php -ls every output file — this catches directive syntax errors and PHP syntax errors introduced by your data before they reach a user. Snapshot-test the generated files with a "golden file" diff so template refactors produce reviewable, byte-level diffs.

Integration tips.

  • Laravel: skip the package — use Blade. Adding a Blade-4 clone inside Laravel buys nothing.
  • Slim/Silex/plain PHP: register your wrapper in the container as $container['view'] and write a 15-line adapter that maps your framework's render call onto SimpleView::render.
  • CLI generators: Symfony Console command + a templates/ directory + --force/--dry-run flags. Print rendered output to stdout on --dry-run; that alone makes templates fast to iterate on.
  • Testing your templates: assert on substrings of the rendered output, and assert on the compiled PHP for structural things (assertStringContainsString('extends Model', $out)). Never assert on exact whitespace unless your templates are whitespace-controlled.

Extension point. The compiler is the extension point: if you need a @datetime($x) directive, subclass/extend the compiler rather than pre-processing template text with str_replace — regex pre-processing of template source is a fast route to unmaintainable generators.

Gotchas and Tips

This is Laravel 4 Blade, so the escaping rules are inverted from what you know. {{ $var }} is raw output and {{{ $var }}} is the escaped form; {!! !!} does not exist. If you port modern Blade knowledge into this package you will silently ship unescaped output. Verify the escaping behaviour against the tests before your first render with user-supplied data, and if the semantics are unclear, escape in PHP (htmlspecialchars($x, ENT_QUOTES)) and echo the already-safe string. Any template that interpolates data you did not produce yourself is a potential XSS.

Never let an untrusted party supply template source. Directives compile to arbitrary PHP. Template files are code; treat the template directory with the same trust boundary as your src/ directory. Do not build a "user-editable emails" feature on top of this.

Stale compiled output is the #1 operational failure. If the package caches by template path without checking mtime — or if your deploy copies templates but not the cache — you get yesterday's output with today's data. Make "clear the compile directory" an explicit, idempotent deploy step, and be aware that OPcache with opcache.validate_timestamps=0 will serve stale compiled files even after you clear the cache directory. Restart PHP-FPM or call opcache_invalidate after clearing.

Writable cache dir, and concurrency. The compile directory must exist and be writable by the web/CLI user; a first run under a different user (root, or a cron job) can leave root-owned files that the next web request cannot overwrite. Under concurrent load, compilation is a read-modify-write on a shared path — if you compile at runtime rather than at deploy, you can get partially written PHP being included. Prefer deploy-time compilation; if you must compile at runtime, ensure your wrapper serialises it or compiles to a per-process temp path and rename()s atomically.

Undefined variables are PHP notices, not friendly errors. There is no $view->share(), no error bag, no "did you mean" — a missing key in the data array surfaces as Undefined variable or Undefined array key inside the compiled file, with a line number pointing at generated code, not your template. When debugging a confusing error, open the compiled PHP file; it is plain, readable, and usually one glance explains everything (e.g. a directive that swallowed a @ in an email address, or an @if that never closed).

Directive gotchas worth knowing up front.

  • A literal @ in output (@example.com, @media, @import in CSS) can be misread as a directive. Escape it or restructure the line.
  • Sections defined inside an @included file are not reliably available to the parent layout — define sections in the child template that does the @extends.
  • @stop vs @show vs @endsection differ; this package is old enough that only some are implemented. Check the compiler, don't assume.
  • @include resolves relative to the configured view root. Nested include paths that work in dev (absolute-ish) will break in prod.
  • Compiled output may carry a leading newline or trailing whitespace from directive lines. For code generators, that matters — run your output through a formatter (php-cs-fixer, php -l + a normaliser) as a post-step rather than contorting the templates.

Age and maintenance: budget for it. Five stars, zero dependents, and a PHP-5-era codebase means you should expect deprecation noise or hard failures on modern PHP (old string-interpolation styles, create_function, each(), ${var} in strings, loose preg_replace with /e). Strategy, in order of preference: (1) fork and vendor it under your own namespace so a rogue upstream tag cannot break your build; (2) pin the exact version in composer.json and lock it; (3) if you do patch, keep the patch as a small diff and add a test that fails without it. Do not put this on a path where a security review is mandatory without first auditing the compiler.

The honest trade-off. The value here is Blade syntax without Laravel in ~1 dependency. If you only need str_replace-level templating, plain PHP files with <?= ?> and extract() cost you nothing and never go stale. If you like the syntax and want something maintained, Twig or league/plates (which is Blade-adjacent and actively maintained) give you the same ergonomics with escaping defaults that match modern expectations. Choose SimpleView deliberately — for its compile-to-PHP model and tiny footprint — and wrap it so that reversing that choice later is a one-class change.

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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route