nongbit / codeigniter-twig
Integrate Twig to CodeIgniter 4
Requires
- php: ^7.4 || ^8.0
- codeigniter4/framework: ^4.4
- twig/intl-extra: ^3.0
- twig/twig: ^3.0
README
Integrate Twig template engine into CodeIgniter 4.
Requirements
- PHP 7.4 or 8.0+
- CodeIgniter 4.4+
- Composer
Installation
composer require nongbit/codeigniter-twig
Setup
1. BaseController
You can use the package either by directly accessing the Twig singleton or by using the provided trait.
Option A: Direct access (without trait)
use Nongbit\Twig\Twig; abstract class BaseController extends Controller { protected $twig; protected function initController(RequestInterface $request, ...$params) { parent::initController($request, ...$params); $this->twig = Twig::getInstance(); } }
Option B: Using the TwigTrait (recommended for simplicity)
use Nongbit\Twig\Traits\TwigTrait; abstract class BaseController extends Controller { use TwigTrait; protected function initController(RequestInterface $request, ...$params) { parent::initController($request, ...$params); $this->initTwig(); } }
2. Optional Configuration
Create app/Config/Twig.php to override defaults:
<?php namespace Config; use CodeIgniter\Config\BaseConfig; class Twig extends BaseConfig { public $autoescape = 'name'; public array $paths = [APPPATH . 'Views']; public string $fileExtension = 'html'; }
Note about
autoescape: See Twig documentation for details.
Usage
Basic Rendering
Without trait (direct singleton access):
public function index() { return $this->twig->render('hello', ['title' => 'Acme']); }
With trait (using display() method):
public function index() { $this->display('hello', ['title' => 'Acme']); }
The display() method outputs directly to the browser, so you don't need to return anything.
Adding View Paths
By default, Twig looks for templates inside APPPATH/Views. To add more locations:
$this->twig->addPath(ROOTPATH . 'templates');
Globals
// Single global $this->twig->addGlobals('appName', 'MyApp'); // Multiple globals $this->twig->addGlobals([ 'appName' => 'MyApp', 'version' => '1.0' ]);
In template:
{{ appName }} - {{ version }}
Filters
$this->twig->addFilters('rot13', 'str_rot13'); // With closure $this->twig->addFilters('reverse', function($string) { return strrev($string); }); // Multiple filters $this->twig->addFilters([ 'rot13' => 'str_rot13', 'reverse' => fn($s) => strrev($s) ]);
In template:
{{ 'Hello'|rot13 }}
Functions
Function behaves similarly to a filter.
$this->twig->addFunctions('now', function() { return date('Y-m-d H:i:s'); });
In template:
{{ now() }}
Built-in Functions
site_url()– generates a site URL (CI4 URL helper)base_url()– generates a base URL (CI4 URL helper)d()– dumps variable using Kint (debug mode only)dd()– dumps and dies using Kint (debug mode only)
These are automatically available in all templates.
Singleton Pattern
This package uses the singleton pattern for the Nongbit\Twig\Twig class. Only one instance exists throughout the application.
Why singleton?
- Twig environment (loader, cache, extensions) is initialized only once per request.
- Compiled templates are reused efficiently.
- Better memory usage and performance.
Drawback
- Hard to reset the instance when needed, especially in unit testing (one test may affect another).
Resetting for Tests
Call \Nongbit\Twig\Twig::reset() to create a fresh instance.
You can place this call either:
- In
setUp()(before each test) – recommended to ensure every test starts with a clean state.
protected function setUp(): void { \Nongbit\Twig\Twig::reset(); }
- In
tearDown()(after each test) – useful if you want to clean up after tests that may have modified the singleton.
protected function tearDown(): void { \Nongbit\Twig\Twig::reset(); }
Choose the option that best fits your test structure. The reset() method is intended for testing only and should never be used in production code.
Development vs Production
The environment is automatically detected using the ENVIRONMENT constant (set in .env or index.php).
| Environment | Debug Mode | Cache |
|---|---|---|
development |
ON (DebugExtension added) | OFF |
production |
OFF | ON (stored in writable/twig) |
In development, you can use {{ dump(var) }} (from DebugExtension) as well as {{ d(var) }} and {{ dd(var) }}.
License
MIT