Skip to content

Extension Isolation

Technomantus Corvi edited this page Sep 6, 2026 · 1 revision

Extension Isolation (HasOwnView)

Extensions meant to be fully removable (tanuki_admin, tanuki_login) shouldn't depend on the main app's view() — that function is tied to views/, includes/head.php/footer.php, and config/nav.php. If an extension's controller called view(), deleting the extension's folder wouldn't be enough; the app's layout would still reference things that no longer exist.

core/HasOwnView.php is a small trait that gives a controller its own, self-contained rendering:

use HasOwnView;

protected function renderOwnView(
    string $baseDir,   // e.g. __DIR__ . '/templates'
    ?string $layout,   // filename (no extension) of the wrapper template, or null
    string $template,  // filename (no extension) of the content template
    array $data = []
): void

When to use it

  • Building a new extension meant to be deletable as a single folder → use HasOwnView, keep its templates inside its own folder.
  • Adding a page to your own project (not an extension) → use $this->view() as normal; you want it to share the main layout, nav, and language switcher.

Example: a minimal extension

my-extension/
├── MyExtensionController.php
└── templates/
    ├── layout.php
    └── index.php
class MyExtensionController extends Controller
{
    use HasOwnView;

    public function index(): void
    {
        $this->renderOwnView(__DIR__ . '/templates', 'layout', 'index', [
            'title' => 'My Extension',
        ]);
    }
}

layout.php receives $content (the rendered index.php) and anything else in $data — write it exactly like a normal HTML page, no dependency on the host project's includes/.

Used by

  • tanuki_adminadmin/templates/ is entirely separate from includes/.
  • tanuki_loginlogin/views/ has its own layout.php, independent of the main site's chrome.

Clone this wiki locally