PHPackages                             younishd/endobox - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. younishd/endobox

AbandonedArchivedLibrary[Templating &amp; Views](/categories/templating)

younishd/endobox
================

minimal template engine.

v4.3.0(6y ago)8672[14 issues](https://github.com/younishd/endobox/issues)1MITPHPPHP ^7.0

Since Jul 18Pushed 5y ago1 watchersCompare

[ Source](https://github.com/younishd/endobox)[ Packagist](https://packagist.org/packages/younishd/endobox)[ Docs](https://github.com/younishd/endobox)[ RSS](/packages/younishd-endobox/feed)WikiDiscussions master Synced today

READMEChangelog (10)Dependencies (2)Versions (14)Used By (1)

[![endobox](endobox.png "made with ♥")](endobox.png)

endobox
=======

[](#endobox)

**minimal template engine.**

[![Build Status](https://camo.githubusercontent.com/511a488c3022c1d79e01e2ceb3ea53a84daf589ecd697b5ec8e6be3206418008/68747470733a2f2f7472617669732d63692e6f72672f796f756e697368642f656e646f626f782e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/younishd/endobox)[![Code Climate](https://camo.githubusercontent.com/bbdbbc715a0965362de027c7c2568096ae84324899ba52e7c17ad7c40dfb9493/68747470733a2f2f636f6465636c696d6174652e636f6d2f6769746875622f796f756e697368642f656e646f626f782f6261646765732f6770612e737667)](https://codeclimate.com/github/younishd/endobox)[![Latest Stable Version](https://camo.githubusercontent.com/ba39c4d526ddd992c9c4ba6d57bad90d0b547d2a2be35c6346efee2b8be9e13e/68747470733a2f2f706f7365722e707567782e6f72672f796f756e697368642f656e646f626f782f76657273696f6e)](https://packagist.org/packages/younishd/endobox)[![Total Downloads](https://camo.githubusercontent.com/cd89202d268bcbc2c612a1dbfe67e0f46b99a2bc1c2e3df20111da335d9ecb78/68747470733a2f2f706f7365722e707567782e6f72672f796f756e697368642f656e646f626f782f646f776e6c6f616473)](https://packagist.org/packages/younishd/endobox)[![License](https://camo.githubusercontent.com/e7dabbf3cd3e1fd702a959cfbae155734e9aab09601e496788e80c5f48af4504/68747470733a2f2f706f7365722e707567782e6f72672f796f756e697368642f656e646f626f782f6c6963656e7365)](https://packagist.org/packages/younishd/endobox)

[![endobox](code.png "made with ♥")](code.png)

🌱 Native PHP syntax📝 Markdown on-board :rocket: Minimal APIWrite templates in vanilla PHP. No need to learn a new syntax.A full-blown Markdown parser is built right in. Yes, it can be combined with PHP!Do powerful things with just a handful of elementary methods.---

Documentation
-------------

[](#documentation)

- [Installation](#installation)
- [Get started](#get-started)
- [Render templates](#render-templates)
- [File extensions](#file-extensions)
- [Data](#data)
- [Chaining &amp; Nesting](#chaining--nesting)
- [Functions](#functions)
- [Cloning](#cloning)

### Installation

[](#installation)

Install endobox is via [Composer](https://getcomposer.org):

```
composer require younishd/endobox
```

You will need **PHP 7.0+**.

### Get started

[](#get-started)

The typical way to configure endobox to load templates for an application looks like this:

```
require_once '/path/to/vendor/autoload.php';

use endobox\Endobox;

$endobox = Endobox::create('path/to/templates');
```

You can add additional template locations:

```
$endobox->addFolder('another/path/to/templates');
```

### Render templates

[](#render-templates)

Instantiate a `Box` for your template:

```
$welcome = $endobox('welcome');
```

Render the template with some variables by calling `render()`:

```
echo $welcome->render([ 'name' => "Alice" ]);
```

The template file itself could look like this:

###### `welcome.php`

[](#welcomephp)

```
Hello, !

```

### File extensions

[](#file-extensions)

endobox decides how to render a template based on the **file extension**.

When you instantiate the template `Box` however, the extension is omitted.

```
$members = $endobox('members'); // no file extension
```

#### PHP: `.php`

[](#php-php)

PHP templates are processed by evaluating the code between PHP tags (i.e., ``) and returning the result.

###### `members.php`

[](#membersphp)

```
Members

```

> ℹ️ **Protip:** The `
    -

```

#### HTML: `.html`

[](#html-html)

HTML templates are always printed as is. No further processing takes place.

###### `members.html`

[](#membershtml)

```
Members

    Alice
    Bob
    Carol

```

### Data

[](#data)

Data is accessible inside a template as simple **variables** (e.g., `$foo`) where the variable name corresponds to the assigned array key or property.

```
Hello, !

```

#### Assign data

[](#assign-data)

There are several ways to assign data to a template box:

```
// via assign(…)
$welcome->assign([ "username" => "eve" ]);

// via object property
$welcome->username = "eve";

// via render(…)
$welcome->render([ "username" => "eve" ]);

// implicitly
$welcome([ "username" => "eve" ]);
```

#### Shared data

[](#shared-data)

Usually, template boxes are isolated from each other. Data that's been assigned to one box, will not be visible from another.

```
$welcome->username = "eve";          // not accessible to 'profile'
$profile->email = "eve@example.com"; // not accessible to 'welcome'
```

If they should share their data however, you can **link** them together:

```
$welcome->link($profile);
```

Now, these template boxes are linked and they share the same data.

###### `welcome.php`

[](#welcomephp-1)

```
Hello, !
Your email address is:

```

###### `profile.php`

[](#profilephp)

```
Profile

    Username:
    Email:

```

Notice how `welcome.php` prints out `$email` which was initially assigned to `$profile` and `profile.php` echoes `$username` even though it was assigned to `$welcome`.

> ℹ️ **Protip:** You can create template boxes using an existing `Box` object (instead of using the `BoxFactory` object) with `$box->create('template')` which has the advantage of **linking the two boxes** together by default.

#### Default values

[](#default-values)

Sometimes it can be useful to supply a **default value** to be printed in case a variable has not been assigned. You can easily achieve that using PHP 7's [**null coalescing operator**](https://en.wikipedia.org/wiki/Null_coalescing_operator#PHP): `??`

```

```

#### Escaping

[](#escaping)

Escaping is a form of data filtering which sanitizes unsafe, user supplied input prior to outputting it as HTML.

endobox provides two shortcuts to the `htmlspecialchars()` function: `$escape()` and its shorthand version `$e()`

```
Hello, !

Hello, !

```

##### Escaping HTML attributes

[](#escaping-html-attributes)

> ⚠️ **Warning:** It's VERY important to always double quote HTML attributes that contain escaped variables, otherwise your template will still be open to injection attacks (e.g., [XSS](https://www.owasp.org/index.php/Cross-site_Scripting_(XSS))).

```

>

```

### Chaining &amp; Nesting

[](#chaining--nesting)

Since you're rarely dealing with just a single template you might be looking for a method that combines multiple templates in a meaningful way.

#### Chaining

[](#chaining)

By **chaining** we mean concatenating templates without rendering them.

Chaining two templates is as simple as:

```
$header($article);
```

Now, calling `->render()` on either `$header` or `$article` will render both templates and return the concatenated result.

> ℹ️ **Protip:** The benefit of not having to render the templates to strings right away is *flexibility*: You can define the layout made out of your templates before knowing the concrete values of their variables.

The general syntax for chaining a bunch of templates is simply:

```
$first($second)($third)($fourth); // and so on
```

Neat.

The more explicit (and strictly equivalent) form would be using `append()` or `prepend()` as follows:

```
$first->append($second)->append($third)->append($fourth);
```

Or…

```
$fourth->prepend($third)->prepend($second)->prepend($first);
```

> ℹ️ **Protip:** Note that the previously seen `Box::__invoke()` is simply an alias of `Box::append()`.

You have now seen how you can append (or prepend) `Box`es together.

Notice however that the variables `$first`, `$second`, `$third`, and `$fourth` were objects of type `Box` which means they needed to be brought to life at some point — probably using the `BoxFactory` object created in the very beginning (which we kept calling `$endobox` in this document).

In other words the complete code would probably look something like this:

```
$first = $endobox('first');
$second = $endobox('second');
$third = $endobox('third');

echo $first($second)($third);
```

It turns out there is a way to avoid this kind of boilerplate code: You can directly pass the name of the template (a `string`) to the `append()` method instead of the `Box` object!

So, instead you could just write:

```
echo $endobox('first')('second')('third');
```

It looks trivial, but there is a lot going on here. The more verbose form would look as follows:

```
echo $endobox->create('first')->append('second')->append('third');
```

This is – in turn – equivalent to the following lines:

```
echo ($_ = $endobox->create('first'))
        ->append($endobox->create('second')->link($_))
        ->append($endobox->create('third')->link($_));
```

Notice that unlike before these (implicitly created) boxes are now all **linked** together automatically, meaning they share the same data.

The rule of thumb is: *Boxes created from other boxes are linked by default.*

#### Nesting

[](#nesting)

A fairly different approach (probably the *template designer* rather than the *developer* way) would be to define some sort of **layout template** instead:

###### `layout.php`

[](#layoutphp)

```

```

Then somewhere in controller land:

```
$layout = $endobox('layout');
$header = $endobox('header');   // header.html
$article = $endobox('article'); // article.php
$footer = $endobox('footer');   // footer.html

echo $layout->render([
    'header' => $header,
    'article' => $article->assign([ 'title' => "How to make Lasagna" ]),
    'footer' => $footer
]);
```

This should be fine, but we can get rid of some boilerplate code here: `$header` and `$footer` really don't need to be variables.

That's where **nesting** comes into play!

Use the `$box()` function to instantiate a template `Box` from *inside* another template:

###### `layout.php`

[](#layoutphp-1)

```

```

Then simply…

```
echo $endobox('layout')->render([
    'article' => $endobox('article')->assign([ 'title' => "How to make Lasagna" ])
]);
```

This is already much cleaner, but it gets even better: By using `$box()` to nest a template `Box` inside another these two boxes will be **linked** by default!

That allows us to condense this even further. Check it out:

###### `layout.php`

[](#layoutphp-2)

```

```

All three templates are now nested using `$box()` and therefore linked to their parent (i.e., `$layout`).

This reduces our controller code to one line:

```
echo $endobox('layout')->render([ 'title' => "How to make Lasagna" ]);
```

Notice how we are assigning a title to the `layout` template even though the actual `$title` variable occurs in the nested `article` template.

> ℹ️ **Protip:** The `$box()` function is also available as a method of `Box` objects (i.e., outside templates): You can instantiate new boxes with `$box->create('template')` where `$box` is some `Box` object that has already been created.

### Functions

[](#functions)

Functions are a cool and handy way of adding reusable functionality to your templates (e.g., filters, URL builders…).

#### Registering functions

[](#registering-functions)

You can register your own custom function (i.e., [closure](https://www.php.net/manual/en/functions.anonymous.php)) by simply assigning it to a template `Box` **just like data!**

Here is a simple function `$day()` which returns the day of the week:

```
$calendar->day = function () { return date('l'); };
```

Inside your template file you can then use it in the same fashion as any variable:

```
Today is .

```

This would look like this (at least sometimes):

```
Today is Tuesday.
```

You can go even further and actually invoke the variable just like any function and actually **pass some arguments** along the way.

Below is a simple closure `$a()` that wraps and escapes some text in a hyperlink tag:

```
$profile->a = function ($text, $href) {
    return sprintf('%s',
            htmlspecialchars($href),
            htmlspecialchars($text));
};
```

Calling this function inside your template would look like this:

```
Follow me on

```

This would produce something like this:

```
Follow me on GitHub
```

#### Default functions

[](#default-functions)

There are a couple of default helper functions that you can use out of the box (some of which you may have already seen):

FunctionDescriptionExample`$box()` or `$b()`Instantiate a `Box` from within another template. (See [Nesting](#chaining--nesting).)```$markdown()` or `$m()`Render some text as Markdown. Useful when the text is user input/stored in a database.```$escape()` or `$e()`Sanitize unsafe user input using `htmlspecialchars()`. (See [Escaping](#escaping).)`
