Views & Templates
Views are plain PHP files under views/. There is no template-compilation step — rendering uses output buffering and include inside a scoped closure.
The $template facade
Every view gets a $template variable — a View facade exposing:
| Method | Purpose |
|---|---|
extends($layout) | Declare the parent layout (e.g. "layouts/app"). |
section($name) / endSection() | Open/close a named section (for layouts). |
slot($name) | Print a stored section (used inside layouts). |
includes($path, $args) | Render a partial from views/. |
primitive($path, $args) | Render a partial from views/primitives/. |
component($name, $props) / endComponent() | Render a component with slot capture. |
Layouts & sections
views/layouts/app.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lunaris Layout</title>
</head>
<body>
<main>
<?php $template->slot("content") ?>
</main>
</body>
</html>
views/welcome.php:
<?php $template->extends("layouts/app") ?>
<?php $template->section("content") ?>
<h1>Welcome to Lunaris</h1>
<p>Current Route: <?= route() ?></p>
<p>Current Url: <?= url() ?></p>
<?php $template->endSection(); ?>
Pass data from an action with response()->view("post", ["title" => "My Post"])->render() — the array is extracted into the view scope.
Partial includes
views/partials/nav.php is included from another view with:
<?php $template->includes("partials/nav") ?>
<?php $template->includes("partials/user", ["user" => $user]) ?>
Primitives
Small inline partials live in views/primitives/. views/primitives/button.php:
<button class="btn"><?= $label ?></button>
<?php $template->primitive("button", ["label" => "Save"]) ?>
// dot paths resolve to directories:
// "forms.button" → views/primitives/forms/button.php
Components with slots
views/components/card.php:
<div class="card">
<h3><?= $title ?></h3>
<div class="card-body"><?= $slot ?></div>
</div>
Everything between component() and endComponent() becomes the $slot:
<?php $template->component("card", ["title" => "Hello"]) ?>
<p>This content becomes the slot.</p>
<?php $template->endComponent() ?>
Props and the $slot variable are available inside the component template; the $template facade is injected there too.
Path resolution
| Call | Resolved path |
|---|---|
response()->view("welcome") | views/welcome.php |
$template->includes("partials/nav") | views/partials/nav.php |
$template->primitive("forms.button") | views/primitives/forms/button.php |
$template->component("card") | views/components/card.php |
Dots are translated to directory separators for primitives and components. A missing file throws an AppException.
View statuses
Render an error view with the right HTTP status by calling status() on the renderer:
return response()
->view("errors/404")
->status(\System\Exceptions\Error::NOT_FOUND)
->render();
Only the three Error enum values (NOT_FOUND, FORBIDDEN, INTERNAL_SERVER_ERROR) are supported for views.
Part of the Lunaris documentation · Source on Codeberg · MIT License