flaphl / inky
Flaphl templating engine, Inky, for PHP 8.2+.
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/flaphl/inky
Requires
- php: >=8.2
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.5
README
Modern, fast, and secure templating engine for PHP 8.2+, part of the Flaphl framework.
Features
- Fast - Compiles templates to optimized PHP code
- Secure - Automatic HTML escaping and XSS protection
- Extensible - Custom filters, functions, and extensions
- Template Inheritance - Block-based template extends system
- Event-Driven - PSR-14 event integration for lifecycle hooks
- Strict Mode - Optional runtime variable validation
- Debuggable - Comprehensive error rendering and profiling
Installation
composer require flaphl/inky
Quick Start
use Flaphl\Fridge\Inky\Engine\{Engine, Loader}; use Flaphl\Fridge\Inky\Compilers\Compiler; // Create engine $engine = new Engine( new Loader([__DIR__ . '/templates']) ); // Render template echo $engine->render('welcome.inky', ['name' => 'World']);
templates/welcome.inky:
{{ # Welcome template }}
Hello, {{ name }}!
Template Syntax
Variables
{{ name }} # Escaped output
{{ user.email }} # Object/array access
{{ items[0] }} # Array index
{{ ! htmlContent }} # Raw/unescaped output
Filters
{{ name | upper }} # Single filter
{{ price | number_format }} # Format numbers
{{ text | upper | trim }} # Chain filters
{{ content | json }} # JSON encode
Control Structures
{{ @if($loggedIn) }}
Welcome back, {{ username }}!
{{ @endif }}
{{ @foreach($items as $item) }}
<li>{{ item }}</li>
{{ @endforeach }}
Template Inheritance
{{ # base.inky }}
<html>
<header>{{ @block header }}Default Header{{ @endblock }}</header>
<main>{{ @block content }}{{ @endblock }}</main>
</html>
{{ # page.inky }}
{{ @extends "base.inky" }}
{{ @block content }}Custom Content{{ @endblock }}
Includes
{{ @include "header.inky" }}
Comments
{{ # This is a comment }}
Extensions
Using Built-in Extensions
use Flaphl\Fridge\Inky\Extensions\CoreExtension; $engine->registerExtension(new CoreExtension());
CoreExtension provides 30+ filters and 15+ functions:
- Filters:
upper
,lower
,trim
,json
,date
,replace
,truncate
,escape
- Functions:
range
,cycle
,min
,max
,sum
,count
,random
Creating Custom Extensions
use Flaphl\Fridge\Inky\Extensions\ExtensionInterface; class MyExtension implements ExtensionInterface { public function getName(): string { return 'my_extension'; } public function getFilters(): array { return [ 'slug' => fn($text) => strtolower(str_replace(' ', '-', $text)), 'reverse' => fn($text) => strrev($text), ]; } public function getFunctions(): array { return [ 'greet' => fn($name) => "Hello, {$name}!", ]; } public function register($engine): void { // Optional: Register custom logic with engine } } $engine->registerExtension(new MyExtension());
Advanced Features
Event Dispatching (PSR-14)
use Flaphl\Fridge\Inky\Events\{PreRenderEvent, PostRenderEvent}; // Set event dispatcher $engine->setEventDispatcher($dispatcher); // Events are automatically dispatched during rendering: // - PreRenderEvent: Before template rendering // - PostRenderEvent: After successful rendering // - RenderErrorEvent: On rendering errors
Strict Mode
// Enable strict variable checking $engine->setStrictMode(true); // Now undefined variables throw InkyException echo $engine->render('template.inky', []); // Throws if {{ undefined }} exists
Performance Profiling
use Flaphl\Fridge\Inky\Utilities\DataCollector; $collector = new DataCollector(); $engine->setDataCollector($collector); // Render templates... // Get statistics $stats = $collector->getStatistics(); echo "Total renders: {$stats['total_renders']}\n"; echo "Total time: {$stats['total_time']}s\n"; echo "Cache hit rate: {$stats['cache_hit_rate']}%\n"; // Get slowest templates $slowest = $collector->getSlowestTemplates(5); foreach ($slowest as $template) { echo "{$template['name']}: {$template['average_time']}s\n"; }
Error Rendering
use Flaphl\Fridge\Inky\Utilities\ErrorRenderer; $renderer = new ErrorRenderer(); $renderer->setFormat('html')->setDebug(true); try { $engine->render('template.inky'); } catch (\Throwable $e) { // Render in HTML, JSON, or text format echo $renderer->renderHtml($e); // or echo $renderer->renderJson($e); // or echo $renderer->renderText($e); }
Template Caching
// Set cache directory for compiled templates $engine->setCacheDirectory(__DIR__ . '/cache'); // Enable auto-reload (recompile on source change) $engine->setAutoReload(true);
Configuration
// Global variables available to all templates $engine->addGlobal('siteName', 'My Website'); $engine->addGlobal('version', '1.0.0'); // Debug mode $engine->setDebug(true); // Strict variables $engine->setStrictMode(true); // Auto-reload templates $engine->setAutoReload(true);
Testing
Run the comprehensive test suite:
composer test # Or with coverage composer test:coverage
Test Statistics:
- 534 tests passing
- 946 assertions
- 100% pass rate
Requirements
- PHP 8.2 or higher
- PSR-6 (Cache) - optional
- PSR-14 (Event Dispatcher) - optional
Contributing
Contributions are welcome! Please follow Flaphl's coding standards and ensure all tests pass.
License
MIT License - see LICENSE file for details.
Credits
Part of the Flaphl Framework by Jade Phyressi.