Plates Template System

repository·v3·Indexed 23 days ago

https://github.com/thephpleague/plates

A fast, extensible, and framework-agnostic native PHP template system. Plates provides modern engine functionality—such as template inheritance, namespacing via folders, and theme hierarchies with fallback logic—while allowing developers to use standard PHP syntax instead of a compiled template language. It is Composer-ready, PSR-2 compliant, and includes built-in escaping helpers for security.

Tokens
14K
Snippets
49
Records
91
Agent score
80%

What's inside Plates

  1. What is Plates template system

    v3

    Plates is a native PHP template system designed for developers who prefer using native PHP instead of learning a new compiled template language (like Twig or Smarty). It is framework-agnostic, Composer-ready, and PSR-2 compliant.

    Key characteristics include:

    • Native PHP: Uses standard PHP syntax within templates, meaning no new language syntax to learn.
    • Template System, not Language: It provides a system to manage templates rather than introducing a proprietary language.
    • Extensibility: Easily extended via functions and extensions.
    • Decoupled Design: Makes templates easy to test and works with any PHP project.
  2. Overview of Plates template system

    v3

    Plates is a native PHP template system designed for developers who prefer using native PHP instead of learning a new compiled template language like Twig or Smarty. It is framework-agnostic, Composer-ready, and PSR-2 compliant.

    Key features include:

    • Native PHP templates: No new syntax to learn; use standard PHP code.
    • Template Inheritance: Increase code reuse with layouts and inheritance.
    • Namespacing: Use template folders to group templates into namespaces.
    • Data Management: Support for sharing data across templates and preassigning data to specific templates.
    • Extensibility: Easily extend the system using functions and extensions.
    • Security: Includes built-in escaping helpers.
  3. How stacked layouts work

    v3

    Plates supports stacking multiple layouts. A template can implement a specific layout (e.g., blog.php), which in turn implements a more general layout (e.g., template.php). This allows you to build a hierarchy of templates, moving from general site structures to specific component structures.

    <?php
    // blog-article.php implements 'blog'
    // blog.php implements 'template'
    
    // 1. The Article
    <?php $this->layout('blog', ['title' => $article->title]) ?>
    <h2><?=$this->e($article->title)?></h2>
    <article>
        <?=$this->e($article->content)?>
    </article>
    
    // 2. The Blog Layout (blog.php)
    <?php $this->layout('template', ['title' => $title]) ?>
    <h1>The Blog</h1>
    <section>
        <article>
            <?=$this->section('content')?>
        </article>
        <aside>
            <?=$this->insert('blog/sidebar')?>
        </aside>
    </section>
    
    // 3. The Main Site Layout (template.php)
    <html>
    <head>
        <title><?=$this->e($title)?></title>
    </head>
    <body>
        <?=$this->section('content')?>
    </body>
    </html>
  4. Inject the Plates Engine into your application

    v3

    Plates is designed for Dependency Injection. You can pass an instance of League\Plates\Engine into your controllers or other application services via their constructors. This allows your application components to access the template engine without needing to know about file system paths or configuration details.

    class Controller
    {
        private $templates;
    
        public function __construct(League\Plates\Engine $templates)
        {
            $this->templates = $templates;
        }
    
        // Create a template object
        public function getIndex()
        {
            $template = $this->templates->make('home');
    
            return $template->render();
        }
    
        // Render a template directly
        public function getIndex()
        {
            return $this->templates->render('home');
        }
    }
  5. Use section fallbacks with fetch() in layouts

    v3

    When designing a layout, you can provide default content for a section using $this->fetch('name'). This is useful for ensuring a part of your UI (like a sidebar or navigation) is never empty, even if the specific page being rendered doesn't define that section.

    In your layout, you can check if a section has content using a conditional, and if not, fetch the default content:

    <div id="sidebar">
        <?php if ($this->section('sidebar')): ?>
            <?=$this->section('sidebar')?>
        <?php else: ?>
            <?=$this->fetch('default-sidebar')?>
        <?php endif ?>
    </div>
    <?php if ($this->section('sidebar')): ?>
        <?=$this->section('sidebar')?>
    <?php else: ?>
        <?=$this->fetch('default-sidebar')?>
    <?php endif ?>
  6. Create and access content sections

    v3

    Sections (or blocks) allow you to capture content within a template and save it for use elsewhere (e.g., in a layout template) instead of rendering it immediately.

    1. Define a section: Use $this->start('name') to begin capturing content and $this->stop() to end it.
    2. Retrieve content: Use $this->section('name') to output the captured content. This can be used in both the current template and the layout template.
    <?php $this->start('welcome') ?>
    
        <h1>Welcome!</h1>
        <p>Hello <?=$this->e($name)?></p>
    
    <?php $this->stop() ?>
    
    <!-- In another template or layout -->
    <?=$this->section('welcome')?>
  7. Understand the difference between Themes and Folders

    v3

    Themes and Folders are distinct features and should not be used interchangeably:

    • Themes: Fallback logic is implicit. All template names are automatically resolved and checked against the entire hierarchy (from last child to first parent).
    • Folders: Fallback logic is opt-in. You must explicitly prefix the template name with the folder name to access it.

    Creating an engine with a single theme is functionally equivalent to using a single directory with no folders.

  8. Access the Engine and Template within an extension

    v3

    Extensions can interact with the core Plates objects:

    1. Engine: The Engine instance is automatically passed as an argument to the register(Engine $engine) method.
    2. Template: The Template object is automatically assigned as a parameter to every function call made by the extension. To access it, you must define a public property named $template on your extension class.
    use League\Plates\Engine;
    use League\Plates\Extension\ExtensionInterface;
    
    class MyExtension implements ExtensionInterface
    {
        protected $engine;
        public $template; // must be public
    
        public function register(Engine $engine)
        {
            $this->engine = $engine;
    
            // Access template data:
            $data = $this->template->data();
    
            // Register functions
            // ...
        }
    }
  9. Core features of Plates

    v3

    Plates provides several features to manage template logic and organization:

    • Layouts and Inheritance: Increase code reuse through template layouts and inheritance models.
    • Template Folders: Group templates into namespaces using folders.
    • Data Management: Share data across templates or preassign specific data to individual templates.
    • Escaping: Includes built-in escaping helpers for security.
    • Extensibility: Supports adding custom functions and extensions to the engine.
  10. Initialize and use the Plates Engine

    v3

    To use Plates, instantiate the League\Plates\Engine class by providing the absolute path to your templates directory. You can then render templates using the render() method, passing the template filename (without the .php extension) and an associative array of data to be used within the template.

    // Create new Plates instance
    $templates = new League\Plates\Engine('/path/to/templates');
    
    // Render a template
    echo $templates->render('profile', ['name' => 'Jonathan']);
  11. Recommended template syntax guidelines

    v3

    To keep Plates templates clean and legible, follow these syntax guidelines:

    • Use HTML with inline PHP: Avoid large blocks of PHP code. Use <?php ... ?> for logic and <?= ... ?> for output.
    • Escape variables: Always escape potentially dangerous variables using the built-in escape functions (e.g., $this->e()).
    • Use short echo syntax: Use <?= for outputting variables. For all other inline PHP, use the full <?php tag. Do not use PHP short tags.
    • Use alternative syntax for control structures: Use the : ... end... syntax (e.g., foreach(...): ... endforeach;) instead of curly brackets.
    • Avoid curly brackets: Never use PHP curly brackets {} in templates.
    • Limit statements per tag: Only use one statement per PHP tag and avoid using semicolons where they are not strictly required.
    • Restrict control structures: Use if and foreach. Avoid for, while, or switch.
    • Avoid class interaction: Never use the use operator; templates should not interact with classes directly.
    • Minimize variable assignment: Avoid assigning variables within the template itself.