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

Twig View Laravel Package

cakephp/twig-view

TwigView integrates the Twig templating engine into CakePHP, letting you build views with clean Twig syntax while using CakePHP helpers, layouts, and conventions. A flexible alternative to PHP templates with extension support.

View on GitHub
Deep Wiki
Context7

Getting Started

cakephp/twig-view is the CakePHP view-layer plugin that swaps the default PHP templates for Twig. If you're arriving from Laravel, think of it as "Blade's job, done by Twig" — same role, different runtime; the integration surface is CakePHP's ViewBuilder, not a service provider, so none of your Laravel Twig-bridge knowledge transfers directly.

Minimal setup:

  1. composer require cakephp/twig-view — match the major line to your framework: 1.x is the maintenance branch (CakePHP 4-era), 2.x is the current line for CakePHP 5. Confirm against Packagist before pinning.
  2. Load the plugin in src/Application::bootstrap():
    $this->addPlugin('TwigView');
    
  3. Point the view layer at it — globally via ViewBuilder::setClassName('TwigView\View\TwigView') in AppView::initialize(), or per-controller with $this->viewBuilder()->setClassName('TwigView\View\TwigView') inside initialize().
  4. Copy templates/Pages/home.php to home.twig, and the layout to templates/layout/default.twig. Twig templates resolve from the same templates/ tree using the .twig extension.

Where to look first: the plugin's docs/ directory (the README is thin), then src/View/TwigView.php for how the Twig environment is constructed, and src/Extension/ for what CakePHP helpers/functions are pre-registered.

First real use case: migrate one read-only action — an index/list page — end to end, including its layout and one element. That exercises template resolution, helper access, and autoescaping in about an hour and surfaces the layout-mismatch problem (below) before you scale to the whole app.

Upgrade note for this release: 1.3.3 is a security backport to the 1.x branch. If you're on 1.3.2 or earlier, treat it as a priority patch (^1.3.3) and render-smoke-test your templates afterwards — security fixes in a templating layer can alter what's callable or how output is escaped.

Implementation Patterns

Incremental, controller-by-controller migration. The cleanest adoption pattern is per-controller setClassName() rather than a global switch. Bake-generated PHP templates keep working for untouched controllers while you convert the ones you care about. Do not try a big-bang conversion of a mature app.

Layout and element co-resolution is the crux. A Twig view cannot extend a PHP layout. When you convert an action, convert its layout and every element it includes in the same commit. Elements are reachable either as Twig includes ({% include 'element/sidebar' %}) or through the view object, which is exposed as _view — {{ _view.element('sidebar') }}.

Helpers are top-level Twig variables. CakePHP helpers land in the context by name, so {{ Html.link('Edit', {'action': 'edit', id}, {'class': 'button'}) }} and {{ Form.create(post) }} read naturally. Anything the plugin doesn't expose, reach through _view: {{ _view.Url.build('/foo') }}. This is the seam to study first — when a helper call fails, it's almost always "wrong variable name" or "wrong argument shape," not a Twig problem.

Translation and formatting come through as Twig functions ({{ __('Hello') }}, {{ __d('domain', 'Message') }}), so i18n keeps working without extra wiring.

Register your own Twig extensions in bootstrap. Custom filters/functions go through the plugin's Configure keys in Application::bootstrap() — this is the extension point for app-specific filters like a money formatter or a markdown filter. Keep them in a small src/Twig/ namespace and register as a list; don't monkey-patch the environment from a view.

Escaping discipline. Twig autoescapes by default. Helper output that is already markup needs |raw, and that is precisely where XSS creeps in. Set a rule for the team: |raw only on values produced by a CakePHP helper, never on request data.

Layouts with blocks. {% extends 'layout/default' %}, {% block content %}, and {{ _view.fetch('content') }} inside the layout mirror the PHP-template equivalent directly, so a layout port is mostly mechanical transcription.

Gotchas and Tips

This is not a Laravel package. No @section/@yield directives, no ServiceProvider, no Blade components. If your team is Laravel-first, budget for the mental shift on helper access (Html.link(...) vs $this->Html->link(...)) and on error output — Twig's exception pages point at template paths relative to templates/, which is fine but unfamiliar.

Compiled-template cache is the #1 time sink. Twig caches compiled templates under tmp/cache/. After changing configuration, adding extensions, or pulling a version bump, clear it (bin/cake cache clear_all, or delete the twig cache directory) before concluding that "nothing changed." In dev, enable Twig's debug option so you get dump() and useful compile errors instead of a blank 500.

Mixed extensions fail loudly and late. A .twig view extending a .php layout throws at render time, not at boot. Grep for layout and element( before declaring a controller converted.

Version-line mismatch. Because 1.x is now in maintenance mode with security-only backports, don't plan new features around it. If you're starting fresh on CakePHP 5, target 2.x; if you're pinned to 1.x, pin ^1.3.3 and expect no new capabilities — only fixes.

Post-upgrade verification for 1.3.3. The changelog is a single line ("backport security fixes"), with no CVE detail in the notes. Pull the linked PR or the security advisory to know what class of issue it is, then smoke-test the templates most likely affected: anything using |raw, anything rendering user-supplied content, and anything calling into helpers with dynamic arguments. Budget a quick manual pass over the layouts of your highest-traffic pages.

Debugging strategy that actually works. When a template silently renders wrong, first check whether the variable is in the context at all ({{ dump(_context) }} with debug on), then whether escaping is mangling it, then whether a stale compiled template is serving old code. That order resolves roughly everything.

Extend rather than fork. The plugin is small; app-specific behavior belongs in a registered Twig extension or a subclass of TwigView set as the view class name. Forking the plugin to patch escaping or helper dispatch will make the next security backport painful — exactly the situation 1.3.3 creates.

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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels