{{ $expression }} output in a Lex template is routed through an escaper before it reaches the browser. By default Lex uses HtmlEscaper, which calls PHP’s htmlspecialchars. You can replace this with your own implementation by providing a class that satisfies EscaperInterface.
The EscaperInterface contract
null, booleans, objects implementing Stringable, or plain strings — and must return a string that is safe to embed verbatim in HTML.
Default behaviour
The built-inHtmlEscaper class converts the five HTML-sensitive characters to their named entity equivalents:
| Input character | Escaped output |
|---|---|
& | & |
< | < |
> | > |
" | " |
' | ' |
htmlspecialchars:
null→ empty string''Stringable→ casts tostringfirstbool→truebecomes'1',falsebecomes''arrayor non-Stringableobject → empty string''
ENT_SUBSTITUTE replaces malformed UTF-8 byte sequences with the Unicode replacement character instead of returning an empty string, which prevents silent data loss.
Implementing a custom escaper
Create a class that implementsEscaperInterface and define the escape() method:
Registering your escaper
Pass an instance tosetEscaper() on the Lexer object:
{{ expr }} output for every template rendered by this Lexer instance is then routed through MyEscaper::escape().
{!! $expr !!} raw echo is not routed through the escaper — it outputs the value verbatim. Only {{ $expr }} uses the escaper.Realistic example: null-safe escaper with additional sanitisation
The following escaper adds two behaviours on top of the default:- Coerces
nullto an empty string so templates never output""or warnings. - Strips HTML tags that survive
htmlspecialcharswhen the value is already a string containing pre-escaped content (useful when integrating with a CMS that stores partially-sanitised content).
When to use a custom escaper
Framework integration
Replace the default escaper with your framework’s built-in XSS filter to keep escaping behaviour consistent across the entire application — for example, integrating with Symfony’s
twig_escape_filter or Laravel’s e() helper logic.Custom output encoding
Output templates into contexts other than HTML — for example, XML documents, plain-text emails, or CSV fields — where the escaping rules differ from
htmlspecialchars.Additional sanitisation
Apply extra content policies on top of HTML escaping — strip specific tags, enforce an allowlist of HTML attributes, or run values through an HTML purifier library before output.
Null / type coercion
Centralise how the template engine handles
null, booleans, and objects so that individual templates do not need explicit null-guard expressions everywhere.Using the Lexer::fromConfig() factory
If you use lex.config.json, apply the escaper after the factory call: