## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require league/plates
Add to composer.json if using Laravel's autoloader:
"autoload": {
"psr-4": {
"App\\": "app/",
"League\\Plates\\": "vendor/league/plates/src/"
}
}
Basic Usage:
Create a template file (resources/views/hello.php):
<h1><?= $name ?></h1>
Render it in a controller:
use League\Plates\Engine;
$loader = new \League\Plates\Engine('resources/views');
echo $loader->render('hello', ['name' => 'World']);
Laravel Integration:
Create a service provider (app/Providers/PlatesServiceProvider.php):
use League\Plates\Engine;
use Illuminate\Support\ServiceProvider;
class PlatesServiceProvider extends ServiceProvider {
public function register() {
$this->app->singleton('plates', function ($app) {
return new Engine($app['path.base'].'/resources/views');
});
}
}
Register in config/app.php:
'providers' => [
// ...
App\Providers\PlatesServiceProvider::class,
],
Use layouts for consistent UI across pages:
// resources/views/layouts/default.php
<!DOCTYPE html>
<html>
<head>
<title><?= $title ?></title>
</head>
<body>
<?= $content ?>
</body>
</html>
Extend in child templates:
// resources/views/home.php
<?php $this->layout('layouts/default') ?>
<?php $this->start('title') ?>
Home Page
<?php $this->stop() ?>
<h1>Welcome!</h1>
Define reusable sections:
// resources/views/partials/nav.php
<nav>
<?php $this->start('nav_items') ?>
<?php $this->stop() ?>
</nav>
Extend in parent templates:
<?php $this->start('nav_items') ?>
<a href="/">Home</a>
<a href="/about">About</a>
<?php $this->stop() ?>
Preassign data globally or per-template:
$loader = new Engine('resources/views');
$loader->setData(['site_name' => 'MyApp']); // Global data
echo $loader->render('home', ['page_title' => 'Dashboard']);
Create custom extensions (e.g., app/Extensions/UrlHelper.php):
use League\Plates\Extension\ExtensionInterface;
class UrlHelper implements ExtensionInterface {
public function register(Engine $engine) {
$engine->registerFunction('url', function ($path) {
return route($path);
});
}
}
Register in your service provider:
$engine->loadExtensions([
new App\Extensions\UrlHelper()
]);
Use in templates:
<a href="<?= url('home') ?>">Home</a>
Organize templates by theme (e.g., resources/views/themes/dark/):
$loader = new Engine('resources/views');
$loader->setFolder('themes/dark'); // Set active theme
$loader->addFolder('themes/light', 'light'); // Fallback theme
Use the asset() helper (included in Plates):
<img src="<?= asset('images/logo.png') ?>" alt="Logo">
Replace Laravel's view composers:
$loader->addFolder('composers', 'composers');
$loader->setData(['user' => auth()->user()]); // Global auth data
Extend Plates to mimic Blade syntax:
$engine->registerFunction('if', function ($condition, $content) {
if ($condition) echo $content;
});
Usage:
@if($show_header)
<header>...</header>
@endif
Bind Plates to Laravel's container:
$this->app->bind('plates', function ($app) {
$engine = new Engine($app['path.base'].'/resources/views');
$engine->loadExtensions([
new App\Extensions\UrlHelper(),
new App\Extensions\AuthHelper(),
]);
return $engine;
});
Attach data in middleware:
public function handle($request, Closure $next) {
$plates = app('plates');
$plates->setData(['user' => auth()->user()]);
return $next($request);
}
Cache compiled templates (Laravel 8+):
$engine = new Engine('resources/views', 'storage/framework/views');
resources/views/Home.php fails to render if called as home.php.strtolower() or configure case-insensitive paths:
$engine = new Engine('resources/views', 'storage/framework/views', [
'fileExtension' => 'php',
'cache' => true,
'autoReload' => true,
]);
start() with stop():
<?php $this->start('sidebar') ?>
<!-- Content -->
<?php $this->stop() ?>
mergeData() to combine data:
$engine->mergeData(['global_key' => 'global_value']);
echo $engine->render('template', ['local_key' => 'local_value']);
$engine->loadExtensions([new MyExtension()]);
$engine->registerFunction('my_func', function() { ... }); // Alternative
ob_start() interferes with Plates rendering.toString():
$template = $engine->make('template');
$content = $template->toString(); // Bypass output buffering
callable type hints break.public function register(Engine $engine): void { ... }
if ($engine->exists('template')) {
echo $engine->render('template');
} else {
throw new \RuntimeException("Template not found");
}
$template = $engine->make('template');
dump($template->data()); // Debug all available data
$engine = new Engine('views', 'cache', [
'autoReload' => true, // For development
]);
Override error handling in your service provider:
$engine->setErrorHandler(function ($error) {
Log::error($error);
abort(500, 'Template Error');
});
$engine = new Engine('resources/views', 'storage/framework/views', [
'cache' => true,
]);
Register extensions once during bootstrapping (not per-request).
Limit nested templates/
How can I help you explore Laravel packages today?