Escapes & Special Characters
Tsuku has two special characters in template text: @ starts a directive, function or inline condition, and { starts a variable when it is followed by a plain variable path and }. Apart from a \ at the very end of a line (a line continuation), everything else - quotes, backslashes, other braces - is ordinary text.
This page is about writing these characters literally. To make data safe for HTML, XML, JSON, CSV or URLs, use the escaping functions described in Security & Escaping.
A Literal @: Write @@
@@ prints a single @ (since 1.4.0):
$template = 'Contact: support@@example.com
Follow @@qoliber';
echo $tsuku->process($template, []);
// Output:
// Contact: [email protected]
// Follow @qoliberIt works anywhere in text, so CSS at-rules and examples of Tsuku syntax are easy to write:
$template = '@@media (max-width: 600px) {
.grid { display: block; }
}';
echo $tsuku->process($template, []);
// Output:
// @media (max-width: 600px) {
// .grid { display: block; }
// }$template = 'Write @@if(...) to start a condition, @@@@ for a literal @@.';
echo $tsuku->process($template, []);
// Output: Write @if(...) to start a condition, @@ for a literal @.A Bare @ Is an Error
An @ that does not start a directive, a function call @name(...) or an inline condition @?{...} throws a ParseException, and the message tells you what to do:
$tsuku->process('Contact: [email protected]', []);
// Throws: ParseException: Invalid @ syntax at line 1, column 17 (write @@ for a literal @)
$tsuku->process('Price @ 9.99', []);
// Throws: ParseException: Invalid @ syntax at line 1, column 7 (write @@ for a literal @)Words that begin with end, else or default are read as those directives: @endpoint is @end followed by point, and @elsewhere is @else followed by where:
$tsuku->process('Call the @endpoint now', []);
// Throws: ParseException: Unexpected @end at line 1, column 10@word( is a function call
An @ followed by a name and an opening parenthesis is a function call, even in CSS: @media(max-width: 600px) calls a function named media. Unknown functions are removed silently in the default SILENT strictness mode, so the at-rule simply disappears from the output. Always write @@media.
$template = '@media(max-width: 600px) { }';
echo $tsuku->process($template, []);
// Output: { }@ Inside Strings
Inside a quoted function argument or a quoted value in a condition, @ is just a character - no escaping needed:
$template = '@upper("[email protected]")
@if(email == "[email protected]")match@end';
$data = ['email' => '[email protected]'];
// Output:
// [email protected]
// matchValues that come from your data are never parsed either, so {user.email} prints an address with @ as it is.
Braces
A { starts a variable only when it is directly followed by a variable path (letters, digits, _ and dots, not starting with a digit) and a closing }. Anything else is plain text, so JSON, CSS and most other brace syntax need no escaping:
$template = '.badge { color: red; } { name } {0} {name|upper} {product.price}';
$data = ['name' => 'Ann', 'product' => ['price' => 9]];
// Output: .badge { color: red; } { name } {0} {name|upper} 9$template = '{"name": @json(name), "tags": []}';
$data = ['name' => 'Ann'];
// Output: {"name": "Ann", "tags": []}Double Braces: Magento Directives Pass Through
{{ is not an escape. Magento CMS and email directives such as {{widget ...}}, {{media ...}}, {{trans ...}}, {{var ...}} or {{store ...}} contain spaces after the name, so they are not variables and pass through unchanged - you can render Magento content with Tsuku without touching them:
$template = '{{widget type="Magento\Cms\Block\Widget\Block" block_id="footer_links"}}
<img src="{{media url="wysiwyg/logo.png"}}" alt="{store_name}">
{{trans "Thank you for your order"}} {{var order.increment_id}}';
$data = ['store_name' => 'Qoliber Shop'];
// Output:
// {{widget type="Magento\Cms\Block\Widget\Block" block_id="footer_links"}}
// <img src="{{media url="wysiwyg/logo.png"}}" alt="Qoliber Shop">
// {{trans "Thank you for your order"}} {{var order.increment_id}}Only a plain variable path inside double braces is replaced: {{name}} is the text {, the variable {name} and the text }:
$template = '{{name}} / {{product.price}}';
$data = ['name' => 'Ann', 'product' => ['price' => 9]];
// Output: {Ann} / {9}A missing variable renders as {} (in SILENT mode). See Widget Support for building your own widget functions.
A Literal
To print a brace pair around a variable name literally, build it with @concat (or pass the text in your data):
$template = '@concat("{", "name}") = {name}';
$data = ['name' => 'Ann'];
// Output: {name} = AnnInline conditions use the same idea: a } inside a quoted value does not end the @?{...}:
$template = '@?{open "}" : "{"}';
$data = ['open' => true];
// Output: }Quotes
Quotes in Function Arguments
Commas inside a quoted function argument never split it, and since 1.4.0 a parenthesis inside a quoted argument no longer ends the call (1.3.0 cut @replace(name, ")", "") off at the first )):
$template = '@replace(name, ")", "")';
$data = ['name' => 'Widget (Pro))'];
// Output: Widget (ProA string can use double or single quotes. To search for a double quote, wrap it in single quotes - a backslash does not escape a quote inside an argument, it stays part of the value:
$template = '@replace(text, \'"\', "")';
$data = ['text' => 'Say "hi"'];
// Output: Say hi$template = '@replace(text, "\"", "")';
$data = ['text' => 'Say "hi"'];
// Output: Say "hi"The second template searches for the two characters \", which do not occur in the text.
Apostrophes in Text
A quote directly after a letter, digit or underscore is an apostrophe, not the start of a string, so contractions and possessives work inside and outside of directives:
$template = '@if(owner)Bob\'s garage@end
@upper("Bob\'s garage")';
$data = ['owner' => true];
// Output:
// Bob's garage
// BOB'S GARAGEBackslashes
A backslash has exactly one meaning in a Tsuku template: \ directly before a line break is a line continuation - both characters are removed. Everywhere else a backslash is printed as it is; it does not escape @, {, quotes or anything else:
$template = <<<'TPL'
C:\Program Files\App \{name} \n \@@ \\server
TPL;
$data = ['name' => 'Ann'];
echo $tsuku->process($template, $data);
// Output: C:\Program Files\App \Ann \n \@ \\serverMind the PHP layer: in a single-quoted PHP string '\\' is one backslash, so '\\\\server' is needed for \\server. A nowdoc (<<<'TPL') passes backslashes through unchanged.
Summary
| You want | Write |
|---|---|
@ | @@ |
@@ | @@@@ |
@media, @import, @font-face in CSS | @@media, @@import, @@font-face |
{ / } / { name } / JSON / CSS braces | as is |
Magento {{widget ...}}, {{media ...}}, {{trans ...}} | as is |
{name} literally | @concat("{", "name}") |
" inside a function argument | '"' |
, ( ) inside a function argument | quote the argument: ")" |
| a backslash | \ (not before a line break) |
| HTML/XML/JSON/CSV/URL-safe data | @html(), @xml(), @json(), @csv(), @url() - see Security & Escaping |
Next Steps
- Security & Escaping → - Escape data for each output format
- Line Continuation → - The one thing a backslash does
- Widget Support → - Custom widget functions
- Variables → - Variable syntax and object access