kenny1911 / twig-view
Type-safe Twig views with template validation and testing capabilities
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/kenny1911/twig-view
Requires
- php: ^8.1
- twig/twig: ^1 || ^2 || ^3
Requires (Dev)
- phpunit/phpunit: ^12.4
- symfony/event-dispatcher: ^6.4||^7.0
- symfony/http-foundation: ^6.4 || ^7.0
- symfony/http-kernel: ^6.4 || ^7.0
This package is auto-updated.
Last update: 2025-11-12 20:48:01 UTC
README
[English][Русский]
A package for typing Twig templates and verifying their correctness during testing.
The Problem
When using Twig templates, errors are often discovered only at runtime because static analyzers cannot effectively verify the correctness of data passed to templates. Common issues include:
- Passing non-existent variables to templates
- Lack of null checks
- Data type mismatches
The Solution
This package provides a system of typed views that explicitly define data structures for templates, along with tools for testing these views.
Installation
composer require kenny1911/twig-view
Usage
Creating a View
<?php use Kenny1911\TwigView\View; /** * @implements View<array{ * name: string * }> */ final class HelloView implements View { public function __construct( private readonly string $name, ) {} #[\Override] public function template(): string { return 'hello.html.twig'; } #[\Override] public function context(): array { return ['name' => $this->name]; } }
Twig Template
hello.html.twig:
<p>Hello {{ name }}</p>
Rendering a View
$viewRenderer->render(new HelloView('World')); // Result: "<p>Hello World</p>"
Symfony Integration
The package includes an event subscriber for automatic integration with Symfony:
# config/services.yaml services: twig.view_renderer: class: Kenny1911\TwigView\ViewRenderer arguments: - '@twig' Kenny1911\TwigView\Symfony\ViewListener: arguments: - '@twig.view_renderer' tags: - { name: kernel.event_subscriber }
Now when a controller returns a View instance, it will automatically be rendered into a Response:
<?php use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; final class HelloController { #[Route('/hello/{name}', name: 'hello')] public function hello(string $name): HelloView { return new HelloView($name); } }
Testing
Use PHPUnit to verify the correctness of all views:
<?php use Kenny1911\TwigView\Test\ViewTest; use Kenny1911\TwigView\ViewRenderer; use PHPUnit\Framework\TestCase; use Twig\Environment; use Twig\Loader\ArrayLoader; final class HelloViewTest extends TestCase { use ViewTest; #[\Override] protected function createViewRenderer(): \Kenny1911\TwigView\ViewRenderer { return new ViewRenderer( new Environment( new ArrayLoader([ 'hello.html.twig' => 'Hello {{ name }}', ]), [ 'strict_variables' => true, ], ), ); } #[\Override] protected function iterateViews(): iterable { yield new HelloView('World'); // Add all test cases for your views here } }
Testing Recommendations
-
Use the Real Twig Environment - Tests should use the same
Twig\Environmentinstance as in production -
Cover All Data Variants - The
iterateViewsmethod should return all possible data combinations for each template -
Test Edge Cases - Pay special attention to cases with
nullvalues and empty data -
Enable strict_variables - This ensures strict variable checking in Twig
Creating a Custom TestCase
In practice, it's recommended to create a base class for testing views that uses the same templates as in production:
<?php abstract class ViewTestCase extends KernelTestCase { use ViewTest; #[\Override] protected function createViewRenderer(): \Kenny1911\TwigView\ViewRenderer { self::bootKernel(); return self::getContainer()->get('twig.view_renderer'); } }
Then your view test would look like this:
final class HelloViewTest extends ViewTestCase { #[\Override] protected function iterateViews(): iterable { yield new HelloView('World'); // Add all test cases for your views here } }
Benefits
- Early Error Detection - Problems are identified during testing, not in production
- Typing - Explicit definition of data structures for each template
- Autocompletion - Better IDE understanding of data structures in templates
- Integration - Easy integration with Symfony and other frameworks
- Flexibility - Ability to test all possible template usage scenarios
Common Issues and Recommendations
- Always Check for
null- This is the most common cause of errors in Twig templates - Use strict_variables - Enable this option for strict variable checking
- Test All Data Variants - Ensure you cover all possible data states
- Use Real Templates - Tests should use the same templates as in production
License
MIT