Template Engine

Syntax, directives, and caching behavior of `.velvet.php` files.

Category: Theming

VelvetCMS ships a compact Blade-inspired engine (VelvetCMS\Services\TemplateEngine) with automatic escaping and compiled template caching.

Rendering life cycle #

  1. ThemeService asks the engine to render layouts/<name> or partials/<name>.
  2. The engine compiles the .velvet.php file to raw PHP under storage/cache/templates/ (hashed per file path).
  3. On subsequent requests the cached PHP is reused until the source file’s mtime changes.

Clear caches on deploy with ThemeService::clearCache() or blow away storage/cache/templates.

Output directives #

Syntax Behavior
{{ $var }} Escaped via the global e() helper (prevents XSS).
{!! $var !!} Raw output—only use with trusted HTML.
@raw ... @endraw Emits content exactly as written (useful for inline scripts).

Control structures #

Directive Equivalent PHP
@if, @elseif, @else, @endif if/elseif/else blocks.
@foreach ($items as $item) / @endforeach Loops over arrays/collections.
@for, @endfor and @while, @endwhile Native loops.
@php ... @endphp Inline PHP block.

Layouts & sections #

@extends('layouts/base')

@section('hero')
  <h1>{{ $page->title }}</h1>
@endsection

@section('content')
  {!! $content !!}
@endsection
  • @extends('layouts/base') must appear near the top of the child template.
  • @section('name') + @endsection capture output; @yield('name', 'fallback') renders it inside the parent.
  • Nested sections are tracked via an internal stack—@endsection must match every @section.

Includes & partials #

  • @include('partials/nav', ['active' => 'docs']) renders another .velvet.php file with merged variables.
  • From PHP you can call $theme->partial('nav', [...]) or $theme->block('cta').

Forms & security helpers #

Directive Rendered HTML
@csrf <input type="hidden" name="_token" value="...">
@method('PUT') <input type="hidden" name="_method" value="PUT">

Pair them with VerifyCsrfToken middleware to protect POST/PUT/PATCH/DELETE requests.

Custom variables & helpers #

The engine exposes everything you pass via $theme->render() plus the helper closures described in the Theme Basics guide. You can attach global helpers using $theme->set() or register functions inside modules (e.g., view() helper wraps ThemeService::view()).

Debug tips #

  • Use dump($vars) or dd($vars) directly inside templates—they’re just PHP under the hood.
  • Template compilation errors show the generated cache path; delete the offending .php file under storage/cache/templates to force recompilation.
  • Keep logic minimal: compute data in controllers or modules, pass it into the view, and reserve templates for presentation.

Knowing these directives and cache mechanics will make writing Velvet themes feel familiar to anyone who has used Blade/Twig, without pulling in a heavyweight dependency.