PHPackages                             text/template - 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. text/template

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

text/template
=============

Simple and secure string-template-engine (Twig-like syntax) with nested if/elseif/else, loops, filters. Simple OOP api: Just one class doing the job (2-lines of code). Fast and secure: No code-generation, no eval'ed() code. Extensible by callbacks. Fully tested. Rich examples included.

v2.8.5(2y ago)38201.1k↓36%7[2 PRs](https://github.com/dermatthes/text-template/pulls)10MITPHPPHP &gt;=5.4CI failing

Since Jul 25Pushed 2y ago3 watchersCompare

[ Source](https://github.com/dermatthes/text-template)[ Packagist](https://packagist.org/packages/text/template)[ Docs](http://text-template.pub.leuffen.de)[ RSS](/packages/text-template/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (3)Versions (27)Used By (10)

Text-Template (Single Class, IF, FOR, FILTERS)
==============================================

[](#text-template-single-class-if-for-filters)

[![Downloads this Month](https://camo.githubusercontent.com/d6ddc61972874903362ba121297cae98a5f7d1364ea2123c7434039959e36121/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646d2f746578742f74656d706c6174652e737667)](https://packagist.org/packages/text/template)[![Latest Stable Version](https://camo.githubusercontent.com/d7f355a6f17dcc2e8f224580bf076c9a010101fd42d5e8c746a841c568efe9ca/68747470733a2f2f706f7365722e707567782e6f72672f746578742f74656d706c6174652f762f737461626c65)](https://github.com/dermatthes/text-template/releases)[![Actions Status](https://github.com/dermatthes/text-template/workflows/tests/badge.svg)](https://github.com/dermatthes/text-template/actions)[![](https://camo.githubusercontent.com/e13e7037e2ef499370a252637abdc9cc2533c6ab666ace744b6076075982f370/68747470733a2f2f7472617669732d63692e6f72672f6465726d6174746865732f746578742d74656d706c6174652e737667)](https://travis-ci.org/dermatthes/text-template)[![Coverage Status](https://camo.githubusercontent.com/8e629f20730771000628bdd19e7f84c9fcfca5b049f3cdb570d11195160a0e28/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6465726d6174746865732f746578742d74656d706c6174652f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/dermatthes/text-template?branch=master)[![Supports PHP 5.4+](https://raw.githubusercontent.com/xp-framework/web/master/static/php-5_4plus.png)](http://php.net/)[![Supports PHP 7.0+](https://raw.githubusercontent.com/xp-framework/web/master/static/php-7_0plus.png)](http://php.net/)[![Homepage](https://camo.githubusercontent.com/72ba5735e3284336ee7f4f6c55298dc263056536c495570c4ab6cc14047b7aeb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f696e666f2d776562736974652d626c75652e737667)](http://text-template.pub.leuffen.de)[![Examples](https://camo.githubusercontent.com/2e254ccd4a7e225d76272f20e686e021f1c6d95e7ad28d09b8f725b5b6aac1c4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7365652d6578616d706c65732d626c75652e737667)](http://text-template.pub.leuffen.de/examples.html)

```
{if user.searching=='template'}This is for you {= user.name }{else}Welcome {= user.name }{/if}

```

Single-Class PHP5/7 template engine with support for if/loops/filters

- **Easy**: No compiling or caching - just parse `input string` into `output string`
- **Secure**: No eval(); no code is generated. No filesystem access needed. Unit-tested.
- **Small**: No dependencies.
- **Features**: Nested loops, if/elseif/else, custom filters, auto-escaping

It is aimed to be a small string Template-Engine to meet e-Mailing or small html-Template demands. It is not meant to be a replacement for pre-compiled full featured Template-Engines like Smarty or Twig.

TextTemplate uses Regular-Expressions for text-Parsing. No code is generated or evaluated - so this might be a secure solution to use in no time-critical situations.

Whilst most template-engines rely on eval'ing generated code and filesystem-access, Text-Template uses a
set of regular-expressions to parse the template. Nor any intermediate code is generated nor any code is eval'ed. So TextTemplate should be more secure than Smarty or Twig by design.

TextTemplate supports infinite-nested loops and sequences.

Basic Example
-------------

[](#basic-example)

```
// 1. Define the Template
$tplStr =  "Matthias"
];

// 3. Parse
$tt = new TextTemplate($tplStr);
echo $tt->apply ($data);
```

Install
-------

[](#install)

I prefer and recommend using [composer](http://getcomposer.com):

```
composer require text/template

```

Flexible tag-start/end
----------------------

[](#flexible-tag-startend)

This documentation refers to the default-tags: Having one bracket `{` as start and one `}` as end delimiter. Of course, they are flexible: If you want to change these, see: `TextTempate::setOpenCloseTagChars()`

Value injection
---------------

[](#value-injection)

Use the value Tag

```
{= varName}

```

To inject a value to the Code. Any variables will be `htmlspecialchars()` encoded by default. To output the RAW content use the `raw`-Filter: `{=htmlCode|raw}`

To access array elements or objects use "." to access sub-elements:

```
{= users.0.name}

```

Loops
-----

[](#loops)

You can insert loops:

```
{for curName in names}
Current Name: {= curName}
{/for}

```

Inside each loop, there are to magick-values `@index0` (index starting with 0) and `@index1` for a index starting with amp1.

```
{for curName in names}
Line {= @index1 }: {= curName}
{/for}

```

Inside loops you can `{break}` or `{continue}` the loop.

Conditions (if)
---------------

[](#conditions-if)

You can use if-conditions:

```
{if someVarName == "SomeValue"}
Hello World
{/if}

```

Shortcut: Test if a variable is null:

```
{if someVarName}
    someVarName is set!
{/if}
{if !someVarName}
    someVarName is not set!
{/if}

```

Complex logical expressions can be made using &amp;&amp; (and), || (or) and brackets.

```
{if someVarName && otherVarName}
    someVarName and otherVarName are set!
{/if}
{if someVarName || otherVarName}
    someVarName or otherVarName are set!
{/if}
{if someVarName || (otherVarName && anotherVarName)}
    Condition is true!
{/if}
{if someVarName && !(otherVarName && anotherVarName)}
    Condition is true!
{/if}

```

You can use filters on values used in comparsions.

```
{if someArray|count > otherArray|count}
    someArray has more items than otherArray
{/if}

```

### Adding Operators

[](#adding-operators)

You can add custom operators for use in conditions.

Adding a new Operator:

```
$tt->addOperator("contains",
    function ($operand1, $operand2) {
        return strpos($operand1, $operand2) !== false;
    }
);
```

### Predefined Operators

[](#predefined-operators)

OperatorDescription==Equal!=Not equal&gt;Greater than&lt;Less than&gt;=Greater than or equal&lt;=Less than or equalConditions (else)
-----------------

[](#conditions-else)

```
{if someVarName == "SomeValue"}
Hello World
{else}
Goodbye World
{/if}

```

Lists of choices:

```
{if someVarName == "SomeValue"}
Hello World
{elseif someVarName == "OtherValue"}
Hello Moon
{else}
Goodbye World
{/if}

```

### Calling Functions

[](#calling-functions)

You can register user-defined functions.

```
$template->addFunction("sayHello",
    function ($paramArr, $command, $context, $cmdParam, $self) {
        return "Hello " . $paramArr["msg"];
    }
);
```

Call the function and output into template

```
{sayHello msg="Joe"}

```

or inject the Result into the context for further processing:

```
{sayHello msg="Joe" > out}
{=out}

```

Processing Exceptions:

Use `!>` to catch exceptions and redirect them to the scope.

`{throw msg="SomeMsg" !> lastErr}`

Or use `!break` or `!continue` to break/continue a loop

### Comments

[](#comments)

Use `{# #}` to add comments (will be stripped from output

```
Template {# Some Comment #}
{# Some
Multiline
Comment #}

```

### Adding Filters

[](#adding-filters)

You can add custom filters or overwrite own filters. The default filter is `html` (htmlspecialchars).

Adding a new Filter:

```
$tt->addFilter ("currency", function ($input, $decimals=2, $decSeparator=",", $thounsandsSeparator=".") {
    return number_format ($input, $decimals, $decSeparator, $thousandsSeparator);
});
```

Call the filter with parameters (parameter-separator `:`):

```
{= variable | currency:2:,:. }

```

Use this filter inside your template

```
{= someVariable | currency }

```

### Predefined Filters

[](#predefined-filters)

NameDescriptionrawDisplay raw data (skip default escaping)singleLineTransform Line-breaks to spacesinivaluelike singleLine including addslashes()htmlhtmlspecialchars()fixedLength::&lt;pad\_char:Pad / shrink the output to charactersinflect:tagConvert to underline tagsanitize:hostnameConvert to hostnamecountReturn count of array### Replacing the default-Filter

[](#replacing-the-default-filter)

By default and for security reason all values will be escaped using the "*DEFAULT*"-Filter. (except if "raw" was selected within the filter section)

If you, for some reason, want to disable this functionality or change the escape function you can overwrite the *DEFAULT*-Filter:

```
$tt->addFilter ("_DEFAULT_", function ($input) {
    return strip_tags ($input);
});
```

or

```
$tt->setDefaultFilter("singleLine");
```

This example will replace the htmlspecialchars() escaper by the strip\_tags() function.

Sections
--------

[](#sections)

Sections are like functions but provide the content they enclose:

```
{sectionxy name="someName"}
Some Content
{/sectionxy}

```

```
{sectionxy name="someName" > out}
Some Content
{/sectionxy}

{= out}

```

To use sections you must just set the callback:

```
$textTemplate->addSection("sectionxy", function ($content, $params, $command, $context, $cmdParam, $self) {
    return "Content to replace section content with";
});
```

### Stripping empty lines

[](#stripping-empty-lines)

```
{strip_empty_lines}
line1

line2
{/strip_empty_lines}

```

### Counting a array

[](#counting-a-array)

```
{trim > countElem}{= var | count}{/trim}
{if countElem == "0" }
{/if}

```

Function return redirection
---------------------------

[](#function-return-redirection)

Append output to a variable.

```
{print >> out}
A
{/print}
{print >> out}
B
{/print}

{= out}

```

Debugging the Parameters
------------------------

[](#debugging-the-parameters)

To see all Parameters passed to the template use:

```
{= __CONTEXT__ | raw}

```

It will output the structure of the current context.

Dealing with undefined Variables
--------------------------------

[](#dealing-with-undefined-variables)

By default text-template will not throw any exceptions when a template tries to access an undefined variable.

To improve debugging, you can switch this behaviour by setting `$softFail` to `false` (Parameter 2 of `apply()` function):

```
try {
    $tt = new TextTemplate("{=someUndefinedName}");
    echo $tt->apply([], false);
    //                  ^^^^^
} catch (UndefinedVariableExceptions $e) {
    echo "UndefinedVariable: {$e->getTriggerVarName()}"
}
```

will return

```
UndefinedVariable: someUndefinedName

```

Changing the tag-open and tag-close chars
-----------------------------------------

[](#changing-the-tag-open-and-tag-close-chars)

Sometimes `{tag}{\tag}` isn't suitable when parsting other template files. You can change the opening and closing chars with the function `setOpenCloseTagChars()`

```
$textTemplate->setOpenCloseTagChars("{{", "}}");
```

The above example will listen to `{{tag}}{{/tag}}`.

Benchmark
---------

[](#benchmark)

Although the parser is build of pure regular-expressions, I tried to avoid too expensive constructions like read ahead, etc.

And we got quite good results:

Template sizeParsing time\[sec\]50kB0.002200kB0.007Contributing, Bug-Reports, Enhancements
---------------------------------------

[](#contributing-bug-reports-enhancements)

If you want to contribute, please send your Pull-Request or open a github issue.

- **Bugs &amp; Feature-Request:** [GitHub Issues](https://github.com/dermatthes/text-template/issues)

**Keeping the tests green**: Please see / provide unit-tests. This project uses `nette/tester` for unit-testing.

This Project uses [kickstart](https://github.com/c7lab/kickstart)'s ready to use development containers based on docker. Just run `./kickstart.sh` to run this project.

To start the development container

```
./kickstart.sh
```

To execute the tests run `kick test` inside the container. (See `.kick.yml`)

About
-----

[](#about)

Text-Template was written by Matthias Leuffen

Join [InfraCAMP](http://infracamp.org)

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity44

Moderate usage in the ecosystem

Community25

Small or concentrated contributor base

Maturity68

Established project with proven stability

 Bus Factor1

Top contributor holds 89.2% 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 ~94 days

Recently: every ~53 days

Total

24

Last Release

1057d ago

Major Versions

v1.2.1 → 2.0.02017-07-26

PHP version history (2 changes)1.0.0PHP &gt;=7.0

v1.1.0PHP &gt;=5.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/878a384d056698a2400e4b7c8858db05a6caebb2c560e67151be36d46d58def0?d=identicon)[dermatthes](/maintainers/dermatthes)

---

Top Contributors

[![dermatthes](https://avatars.githubusercontent.com/u/13380559?v=4)](https://github.com/dermatthes "dermatthes (66 commits)")[![MartinMystikJonas](https://avatars.githubusercontent.com/u/2094752?v=4)](https://github.com/MartinMystikJonas "MartinMystikJonas (5 commits)")[![AlGoore](https://avatars.githubusercontent.com/u/4050047?v=4)](https://github.com/AlGoore "AlGoore (1 commits)")[![inhere](https://avatars.githubusercontent.com/u/5302062?v=4)](https://github.com/inhere "inhere (1 commits)")[![mullikine](https://avatars.githubusercontent.com/u/1020987?v=4)](https://github.com/mullikine "mullikine (1 commits)")

---

Tags

filterhtml5loopphp7regular-expressionsmartytemplatetextpatterntexttemplatetwigtwigmailtemplatefiltertextsmartylooprenderforif

### Embed Badge

![Health badge](/badges/text-template/health.svg)

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

###  Alternatives

[latte/latte

☕ Latte: the intuitive and fast template engine for those who want the most secure PHP sites. Introduces context-sensitive escaping.

1.3k15.7M683](/packages/latte-latte)[jenssegers/blade

The standalone version of Laravel's Blade templating engine for use outside of Laravel.

8661.2M109](/packages/jenssegers-blade)[wyrihaximus/twig-view

Twig powered View for CakePHP

804.7M1](/packages/wyrihaximus-twig-view)[ytake/laravel-smarty

Smarty template engine for Laravel and Lumen

87401.6k](/packages/ytake-laravel-smarty)[phug/phug

Pug (ex-Jade) facade engine for PHP, HTML template engine structured by indentation

67292.2k13](/packages/phug-phug)[oro/twig-inspector

Oro Twig Inspector adds the possibility to find twig templates and blocks used for rendering HTML pages faster during development

47532.6k14](/packages/oro-twig-inspector)

PHPackages © 2026

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