PHPackages                             vanilla/ebi - 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. vanilla/ebi

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

vanilla/ebi
===========

A template engine made with HTML.

v0.3.6(8y ago)3381[6 issues](https://github.com/vanilla/ebi/issues)MITPHPPHP &gt;=5.6.0

Since Jun 14Pushed 8y agoCompare

[ Source](https://github.com/vanilla/ebi)[ Packagist](https://packagist.org/packages/vanilla/ebi)[ RSS](/packages/vanilla-ebi/feed)WikiDiscussions master Synced 3d ago

READMEChangelog (10)Dependencies (4)Versions (21)Used By (0)

The Ebi Template Language
=========================

[](#the-ebi-template-language)

[![Build Status](https://camo.githubusercontent.com/104b7677a931ce493d19b6056661bbad55a6822f5654b84d3059a0d54317b83e/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f76616e696c6c612f6562692e7376673f7374796c653d666c6174)](https://travis-ci.org/vanilla/ebi)[![Coverage](https://camo.githubusercontent.com/7987e5dce82a70b7e412b9ebb421092c7beefa520ff500ca7e154bb39950b7ea/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f636f7665726167652f672f76616e696c6c612f6562692e7376673f7374796c653d666c6174)](https://scrutinizer-ci.com/g/vanilla/ebi/)[![Packagist Version](https://camo.githubusercontent.com/b9e0c40a5902094242bef38dbc2987c077475deb42b30f14cfe0e83a3ba0e848/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f76616e696c6c612f6562692e7376673f7374796c653d666c6174)](https://packagist.org/packages/vanilla/ebi)[![MIT License](https://camo.githubusercontent.com/be4aa0316efc1b5b12353528dab80eb1cecedf6db1e19e422e17b1c449e597ba/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f76616e696c6c612f6562692e7376673f7374796c653d666c6174)](https://camo.githubusercontent.com/be4aa0316efc1b5b12353528dab80eb1cecedf6db1e19e422e17b1c449e597ba/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f76616e696c6c612f6562692e7376673f7374796c653d666c6174)[![CLA](https://camo.githubusercontent.com/05d022e482e6a2a22f432b1344633e57ea4fdf3b5dbab979acba5972b6885268/68747470733a2f2f636c612d617373697374616e742e696f2f726561646d652f62616467652f76616e696c6c612f656269)](https://cla-assistant.io/vanilla/ebi)

The Ebi template language uses basic HTML and special attributes for a simple yet powerful template language.

The Basics of a Template
------------------------

[](#the-basics-of-a-template)

In general you write normal HTML. Data is included in the template by including it between `{...}`. Other special functionality is added via special template attributes.

Data is included in a template by putting it between `{...}` braces. This is known as "interpolation" and there are quite a few options.

### Fields

[](#fields)

To include a field from your data use its name.

```
Hello {firstName} {lastName}.
```

This will include the "firstName" and "lastName" database keys. You can access deeply nested arrays by separating field names with dots.

```
Hello {user.firstName} {user.lastName}.
```

*You might be tempted to put a dash in your field names. However this will not work as expected because the field names are interpreted as expressions. So for example {is-on} will be interpreted as "is" minus "on"!*

### Meta

[](#meta)

You can add global meta data to all templates which are then accessed by putting an `@` sign before a variable name.

```
{@title}
```

```
$ebi = new Ebi(...);
$ebi->setMeta('title', 'Welcome to the Page');

$ebi->write(...);
```

The meta array is a good place to put configuration information that is separate from template data. Since it is global to all components you can access it from within any component regardless of scope.

### Operators

[](#operators)

When writing fields you aren't limited to just field names. A fairly rich expression syntax is supported.

TypeOperatorsArithmetic+,-,\*,/,%,\*\*Bitwise&amp;,|,^Comparison==,===,!=,!==,&lt;,&gt;,&lt;=,&gt;=,matchesLogical&amp;&amp;,||,!String Concatenation~Arrayin, not inRange..Ternarycond ? 'yes' : 'no'
cond ?: 'no'
cond ? 'yes'### Functions

[](#functions)

Functions are called using the `functionName()` syntax. Ebi provides a set of default functions that map to PHP's standard library.

FunctionDescriptionPHP FunctionabsAbsolute value of a number.[abs](https://secure.php.net/manual/en/function.abs.php)arrayColumnReturn the values from a single column in the input array.[array\_column](https://secure.php.net/manual/en/function.array-column.php)arrayKeyExistsChecks if the given key or index exists in the array.[array\_key\_exists](https://secure.php.net/manual/en/function.array-key-exists.php)arrayKeysReturn the keys of an array.[array\_keys](https://secure.php.net/manual/en/function.array-keys.php)arrayMergeMerge one or more arrays.[array\_merge](https://secure.php.net/manual/en/function.array-merge.php)arrayMergeRecursiveMerge two or more arrays recursively.[array\_merge\_recursive](https://secure.php.net/manual/en/function.array-merge-recursive.php)arrayReplaceReplaces elements from passed arrays into the first array.[array\_replace](https://secure.php.net/manual/en/function.array-replace.php)arrayReplaceRecursiveReplaces elements from passed arrays into the first array recursively.[array\_replace\_recursive](https://secure.php.net/manual/en/function.array-replace-recursive.php)arrayReverseReturn an array with elements in reverse order.[array\_reverse](https://secure.php.net/manual/en/function.array-reverse.php)arrayValuesReturn all the values of an array.[array\_values](https://secure.php.net/manual/en/function.array-values.php)base64EncodeEncodes data with MIME base64.[base64\_encode](https://secure.php.net/manual/en/function.base64-encode.php)ceilRound fractions up.[ceil](https://secure.php.net/manual/en/function.ceil.php)componentExistsChecks if the given component name exists.countCount the number of items in an array.[count](https://secure.php.net/manual/en/function.count.php)emptyCheck to see if a string or array is empty.[empty](https://secure.php.net/manual/en/function.empty.php)floorRound fractions down.[floor](https://secure.php.net/manual/en/function.floor.php)formatDateFormat a date.[date\_format](https://secure.php.net/manual/en/function.date-format.php)formatNumberFormat a number with grouped thousands.[number\_format](https://secure.php.net/manual/en/function.number-format.php)hasChildrenChecks if the component has children passed to it. Pass the name of a block to test for that specific child.htmlEncodeConvert special characters to HTML entities.[htmlspecialchars](https://secure.php.net/manual/en/function.htmlspecialchars.php)isArrayFinds whether a variable is an array.[is\_string](http://php.net/manual/en/function.is-array.php)isBoolFinds out whether a variable is a boolean.[is\_bool](http://php.net/manual/en/function.is-bool.php)isIntFind whether the type of a variable is integer[is\_int](http://php.net/manual/en/function.is-int.php)isScalarFinds whether a variable is a scalar.[is\_scalar](http://php.net/manual/en/function.is-scalar.php)isStringFind whether the type of a variable is string.[is\_string](http://php.net/manual/en/function.is-string.php)joinJoin the elements of an array into a string.[implode](https://secure.php.net/manual/en/function.implode.php)lcaseLowercase a string.[strtolower](https://secure.php.net/manual/en/function.strtolower.php), [mb\_strtolower](https://secure.php.net/manual/en/function.mb-strtolower.php)lcfirstLowercase the first letter of a word.[lcfirst](https://secure.php.net/manual/en/function.lcfirst.php)ltrimLeft trim a string.[ltrim](https://secure.php.net/manual/en/function.ltrim.php)maxFind highest value.[max](https://secure.php.net/manual/en/function.max.php)minFind the lowest value.[min](https://secure.php.net/manual/en/function.min.php)queryEncodeGenerate a URL-encoded query string.[http\_build\_query](https://secure.php.net/manual/en/function.http-build-query.php)roundRound a number.[round](https://secure.php.net/manual/en/function.round.php)rtrimRight trim a string.[rtrim](https://secure.php.net/manual/en/function.rtrim.php)sprintfReturn a formatted string.[sprintf](https://secure.php.net/manual/en/function.sprintf.php)strlenReturn the length of a string.[strlen](https://secure.php.net/manual/en/function.strlen.php), [mb\_strlen](https://secure.php.net/manual/en/function.mb-strlen.php)substrReturn a part of a string.[substr](https://secure.php.net/manual/en/function.substr.php), [mb\_substr](https://secure.php.net/manual/en/function.mb-substr.php)trimTrim a string.[trim](https://secure.php.net/manual/en/function.trim.php)ucaseUppercase a string.[strtoupper](https://secure.php.net/manual/en/function.strtoupper.php), [mb\_strtoupper](https://secure.php.net/manual/en/function.mb-strtoupper.php)ucfirstUppercase the first letter of a word.[ucfirst](https://secure.php.net/manual/en/function.ucfirst.php)ucwordsUppercase the first letter in each word of a string.[ucwords](https://secure.php.net/manual/en/function.ucwords.php)urlEncodeURL-encode according to RFC 3986.[rawurlencode](https://secure.php.net/manual/en/function.rawurlencode.php)### Literals

[](#literals)

You can include literals in expressions too.

TypeNotationExamplestringEnclose in single or double quotes.'hello'numberWrite the number without quotes.123arrayUse JSON notation.\[1, 2, 3\]objectUse JSON notation without quoted keys.{ foo: 'bar' }booleanUse the `true` and `false` constants.truenullUse `null` constant.null### Unescaping Data

[](#unescaping-data)

All variables are HTML escaped by default. If you want to return unescaped HTML, you can use the **unescape** function.

```
{unescape(bodyHtml)}
```

Template Attributes
-------------------

[](#template-attributes)

Most of Ebi's functionality is accessed using template attributes. These are HTML style attributes that you add to any tag in your template to add logic. All of Ebi's attributes start with an `x-` prefix to help you differentiate between Ebi attributes and regular HTML attributes.

*The letter "X" was chosen to mean "extended attribute" and was inspired by the same prefix in HTTP headers.*

### x-if

[](#x-if)

Only display an element if the condition is true.

```

There are no items!

```

```
if (empty($props['items'])) {
    echo "There are no items!";
}
```

### x-else

[](#x-else)

Add an else element in conjunction with an if element.

```

    Welcome!

    Sign in to participate.

```

```
if ($props['signedIn']) {
    echo 'Welcome!';
} else {
    echo 'Sign in to participate.';
}
```

### x-each

[](#x-each)

Loop over elements.

```

    Hi {firstName} {lastName}!

```

```
echo '';
foreach ($props['people'] as $props1) {
    echo 'Hi ',
        $this->escape($props1['firstName']),
        ' ',
        $this->escape($props1['lastName']);
}
echo '';
```

#### x-each x-as

[](#x-each-x-as)

Name the iterator element so that you can still reference the parent.

```

    {name}: {comment.body} #{i}

```

```
echo '';
foreach ($props['comments'] as $i1 => $props1) {
    echo '',
        $this->escape($props['name']),
        ': ',
        $this->escape($props1['body']),
        ' #',
        $this->escape($i1)
        '';
}
echo '';
```

*Tip: If you want to access the key of an array, but still want to access its values without dot syntax then you can use `x-as="key this"`.*

#### Iterator Variables

[](#iterator-variables)

When you specify **x-as** with an **x-each** there three special iterator variables you'll have access to: **index, first, last**.

```

    {item}

```

So if you specify a key in **x-as** you can access the special variables as if they were properties of the key. The resulting PHP is a bit more verbose, but straight forward enough.

```
echo '';
$count1 = count($props);
$index1 = -1;
foreach ($props as $i1 => $props1) {
    $index1++;
    $first1 = $index1 === 0;
    $last1 = $index1 === $count1 - 1;
    echo '',
        $this->escape($props1),
        '';
}
echo '';
```

### x-empty

[](#x-empty)

Specify a template when there are no items.

```

    {body}
    There are no messages.

```

```
echo '';
if (empty($props['messages'])) {
    echo 'There are no messages.';
} else {
    foreach ($props['message'] as $i1 => $props1) {
        echo '',
            $this->escape($props1['body']),
            '';
    }
}
echo '';
```

### x-with

[](#x-with)

Pass an item into a template.

```

    Hello {name}.

```

```
$props1 = $props['user'];
echo '',
    'Hello ',
    $this->escape($props1['name']),
    '';
```

#### x-with x-as

[](#x-with-x-as)

You can give an alias to the data referenced with `x-with` so that you can still access the parent data within the block. A good use for this is for performing a calculation on some data and assigning it to a variable.

```
{title}
```

```
$props1 = trim(ucfirst($props['sentence']));
if (!empty($props1)) {
    echo $this->escape($props1);
}
```

### x-literal

[](#x-literal)

Don't parse templates within a literal.

```
Hello {username}
```

```
echo 'Hello {username}';
```

### x-tag

[](#x-tag)

Sometimes you want to dynamically determine the name of a tag. That's where the the `x-tag` attribute comes in.

```
{heading}
```

```
echo '',
    $this->escape($props['heading']),
    '';
```

#### Conditional wrappers with x-tag

[](#conditional-wrappers-with-x-tag)

If your template uses has an **x-tag** expression that results in an empty string then the tag will not render, *but the tag contents will*. In this way you can use **x-tag** do implement conditional wraps.

If an **x-tag** expression evaluates to **true** then the tag that it is in will be used.

```
Hello!
```

The above example will just render `Hello!`. This notation is useful when you have a boolean expression that determines when to render a wrapper.

Template Tags
-------------

[](#template-tags)

Most of Ebi's functionality uses special attributes. However, there are a couple of special tags supported.

### The `` Tag

[](#the-script-typeebi-tag)

Usually, you write expressions by enclosing them in braces (`{..}`). However, braces don't themselves allow brace characters. They also don't allow multi-line expressions. When you have such an expression you can instead enclose it in a `` tag.

```

  join(
    "|",
    [1, 2, 3]
  )

```

```
echo $this->escape(join('|', [1, 2, 3]);
```

#### ``

[](#script-x-unescape)

If you don't want to escape the output in an `` tag then add the `x-unescape` attribute. You don't have to include the `type="ebi"` in this case.

```
join('>', [1, 2, 3])
```

```
echo join('>', [1, 2, 3]);
```

#### ``

[](#script-x-as)

You can also use the `` tag with an `x-as` attribute to create an expression variable that can be used later in the template. You don't have to include the `type="ebi"` in this case.

```
trim(ucfirst(sentence))
{title}
```

```
$title = trim(ucfirst($props['sentence']));
if (!empty($title) {
    echo '',
        $this->escape($title),
        '';
}
```

### The `` Tag

[](#the-x-tag)

Sometimes you will want to use an ebi attribute, but don't want to render an HTML tag. In this case you can use the `x` tag which will only render its contents.

```
Welcome back
```

```
if ($props['signedIn']) {
  echo 'Welcome back';
}
```

Components
----------

[](#components)

Components are a powerful part of Ebi. With components you can make re-usable templates that can be included in other templates. Here are some component basics:

- Each template is a component. You can declare additional components in a template too.
- Components are lowercase. It is recommended that you use dashes to separate words in component names. Make sure to name your template files in lowercase to avoid issues with case sensitive file systems.
- Components are used by declaring an HTML element with the component's name. Components create custom tags!
- You can pass data into components with contributes. If you want to pass all of the current template's data into a component use the `x-with` attribute.
- It is strongly recommended you don't name your components with an `x-` prefix as that may be used for future functionality.

### x-component

[](#x-component)

Define a component that can be used later in the template.

```
{date(date, 'r')}

```

```
$this->register('long-date', function ($props) {
    echo '',
        htmlspecialchars(date($props['date'], 'r')),
        '';
});

$this->render('long-date', ['date' => $props['dateInserted']]);
```

Components must begin with a capital letter or include a dash or dot. Otherwise they will be rendered as normal HTML tags.

### Component Data

[](#component-data)

By default, components inherit the current scope's data. There are a few more things you can do to pass additional data into a component.

#### Pass Data Using `x-with`

[](#pass-data-using-x-with)

If you want to pass data other than the current context into a component you use the `x-with` attribute.

```

   {author.username}

  {unescape(body)}

```

### x-children and x-block

[](#x-children-and-x-block)

You can define custom content elements within a component with blocks. An unnamed block will use the same tag it's declared in.

```

  Hello world!
  When you put yourself out there you will always do well.

```

The blocks get inserted into the component when it is used.

```

  Hello world!

    Hello world!
    When you put yourself out there you will always do well.

```

*Tip: You can use the **hasChildren()** function to determine if a particular block has been passed to your component.*

### x-include

[](#x-include)

Sometimes you want to include a component dynamically. In this case you can use the `x-include` attribute.

```
Hello {name}
Goodbye {name}

```

```
$this->register('hello', function ($props) {
    echo 'Hello ',
        $this->escape($props['name']);
});

$this->register('goodbye', function ($props) {
    echo 'Goodbye ',
        $this->escape($props['name']);
});

$this->write($props['salutation'], $props);
```

HTML Utilities
--------------

[](#html-utilities)

### Attribute expressions

[](#attribute-expressions)

When you specify an attribute value as an expression then the attribute will render differently depending on the value.

ValueBehaviortrueRenders just the attribute.false, nullWon't render the attribute.aria-\* attributeValues of true or false render as string values.other valuesrender as normal attribute definitions.### Examples

[](#examples)

The following templates:

```

```

Will result in the following output:

```

```

### CSS class attributes

[](#css-class-attributes)

When you assign a css class with data you can pass it an array or an object.

#### Array class attributes

[](#array-class-attributes)

```
Hello
```

All elements of the array are rendered as separate classes.

```
Hello
```

#### Object class attributes

[](#object-class-attributes)

```
Hello
```

When passing an object as the class attribute the keys define the class names and the values define whether they should be included. In this way you can enable/disable CSS classes with logic from the template's data.

Note the double braces in the above example. The first brace tells us we are using variable interpolation and the second brace wraps the object in JSON notation.

### Style attributes

[](#style-attributes)

When you assign the style attribute with data you can pass it an associative array or object expression. When you do so the keys and values will be treated as CSS properties and values respectively.

```
Hello
```

The style object will be converted into a string.

```
Hello
```

Notice how the font-family was given an array and correctly converted to CSS.

#### Boolean style values

[](#boolean-style-values)

There are a few CSS properties that can accept a true or false value:

PropertyValueResultborderfalseborder: nonebox-shadowfalsebox-shadow: nonedisplayfalsedisplay: nonevisibilitytruevisibility: visiblevisibilityfalsevisibility: hidden### Whitespace

[](#whitespace)

Whitespace around block level elements is trimmed by default resulting in more compact output of your HTML.

### HTML Comments

[](#html-comments)

Any HTML comments that you declare in the template will be added as PHP comments in the compiled template function. This is useful for debugging or for static template generation.

```

wut!?
```

```
function ($props) {
    // Do something.
    echo 'wut!?';
};
```

Using Ebi in Code
-----------------

[](#using-ebi-in-code)

The **Ebi** class is used to compile and render Ebi templates. You should only need one instance of the class to render any number of templates.

### Basic Usage

[](#basic-usage)

```
$ebi = new Ebi(
    new FilesystemLoader('/path/to/templates'),
    '/path/to/cache'
);

$ebi->write('component', $props);
```

In this example an **Ebi** object is constructed and a basic component is written to the output.

###  Health Score

23

—

LowBetter than 27% of packages

Maintenance0

Infrequent updates — may be unmaintained

Popularity16

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~9 days

Total

17

Last Release

3102d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/da29e060f227028e8ee38bb5873ba2188fb5236b20b3dffec766c768019d8bd8?d=identicon)[tburry](/maintainers/tburry)

![](https://www.gravatar.com/avatar/ea17fedfd653c4692cf93a4faada50927cef9537dafed0dd4b1517e54fd71728?d=identicon)[charrondev](/maintainers/charrondev)

![](https://www.gravatar.com/avatar/22fabd6a0972f403ffeec3aba8cffd2d86fb05039e066d9e90504243fc59bc00?d=identicon)[initvector](/maintainers/initvector)

---

Top Contributors

[![tburry](https://avatars.githubusercontent.com/u/97432?v=4)](https://github.com/tburry "tburry (90 commits)")

---

Tags

non-production

### Embed Badge

![Health badge](/badges/vanilla-ebi/health.svg)

```
[![Health](https://phpackages.com/badges/vanilla-ebi/health.svg)](https://phpackages.com/packages/vanilla-ebi)
```

###  Alternatives

[friendsofsymfony/ckeditor-bundle

Provides a CKEditor integration for your Symfony project.

53014.3M49](/packages/friendsofsymfony-ckeditor-bundle)[nucleos/antispam-bundle

This bundle provides some basic features to reduce spam in symfony forms.

52105.1k](/packages/nucleos-antispam-bundle)[iq2i/storia-bundle

UI Storia bundle

144.6k](/packages/iq2i-storia-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
