Variables
Variables are the foundation of Tsuku templates. They allow you to output data from your data array into the template.
Basic Syntax
Use curly braces {} to output variables:
$template = 'Hello, {name}!';
$data = ['name' => 'World'];
$result = $tsuku->process($template, $data);
// Output: Hello, World!Dot Notation
Access nested data using dot notation:
$template = 'Product: {product.name}
Price: ${product.price}
Category: {product.category.name}';
$data = [
'product' => [
'name' => 'Widget',
'price' => 29.99,
'category' => [
'name' => 'Electronics',
],
],
];
$result = $tsuku->process($template, $data);
// Output:
// Product: Widget
// Price: $29.99
// Category: ElectronicsArray Index Access
Access array elements by index:
$template = 'First: {items.0}
Second: {items.1}
Third: {items.2}';
$data = [
'items' => ['Apple', 'Banana', 'Cherry'],
];
$result = $tsuku->process($template, $data);
// Output:
// First: Apple
// Second: Banana
// Third: CherrySmart Object/Array Access
Tsuku automatically detects the best way to access your data. For every segment of a path such as product.name it tries these 5 strategies in order and uses the first one that exists:
- Array key:
$product['name'] - Getter method:
$product->getName() - Boolean getter:
$product->isName() - Method with the same name:
$product->name() - Public property:
$product->name
Strategy 1: Array Access
$data = [
'product' => ['name' => 'Widget'],
];
echo $tsuku->process('{product.name}', $data);
// Accesses: $product['name']
// Output: WidgetStrategy 2: Getter Methods
class Product {
private $name = 'Widget';
public function getName() {
return $this->name;
}
}
$data = ['product' => new Product()];
echo $tsuku->process('{product.name}', $data);
// Calls: $product->getName()
// Output: WidgetStrategy 3: Boolean Getters
class Product {
public function isAvailable() {
return true;
}
}
$data = ['product' => new Product()];
echo $tsuku->process('{product.available}', $data);
// Calls: $product->isAvailable()
// Output: 1Strategy 4: Direct Method Calls
class Product {
public function total() {
return 99.99;
}
}
$data = ['product' => new Product()];
echo $tsuku->process('{product.total}', $data);
// Calls: $product->total() - write the path without parentheses
// Output: 99.99A path never contains parentheses: {product.total()} is not a variable and is printed as literal text.
Strategy 5: Public Properties
class Product {
public $name = 'Widget';
}
$data = ['product' => new Product()];
echo $tsuku->process('{product.name}', $data);
// Accesses: $product->name
// Output: WidgetPrivate and protected properties are never read directly - expose them through a getter.
Keys That Contain Dots
If the data has a key that literally contains the dots, that key wins over the nested lookup:
$data = [
'a.b' => 'flat key',
'a' => ['b' => 'nested'],
];
echo $tsuku->process('{a.b}', $data);
// Output: flat keyDeep Nesting
Access deeply nested data:
$template = '{order.customer.address.city}';
$data = [
'order' => [
'customer' => [
'address' => [
'city' => 'New York',
],
],
],
];
$result = $tsuku->process($template, $data);
// Output: New YorkMissing Variables
By default, missing variables output as empty strings. A value of null counts as missing:
$template = 'Name: {name}
Missing: [{missing}]
Phone: [{phone}]';
$data = ['name' => 'John', 'phone' => null];
$result = $tsuku->process($template, $data);
// Output:
// Name: John
// Missing: []
// Phone: []That is the default SILENT strictness mode. In WARNING mode the missing variable still renders empty but is reported by getWarnings(); in STRICT mode it throws:
use Qoliber\Tsuku\Tsuku;
use Qoliber\Tsuku\StrictnessMode;
$tsuku = new Tsuku(StrictnessMode::STRICT);
$tsuku->process('Hello {missing}', []);
// Throws: TsukuException: Variable 'missing' not found in dataUsing @default() Function
Provide fallback values for missing data:
$template = 'Name: @default(name, "Guest")
Stock: @default(stock, "0")';
$data = [];
$result = $tsuku->process($template, $data);
// Output:
// Name: Guest
// Stock: 0Working with Objects
Tsuku handles objects intelligently:
class Product {
private $name = 'Widget';
private $price = 99.99;
private $inStock = true;
public function getName() { return $this->name; }
public function getPrice() { return $this->price; }
public function isInStock() { return $this->inStock; }
public function getFormattedPrice() {
return '$' . number_format($this->price, 2);
}
}
$template = 'Product: {product.name}
Price: {product.formattedPrice}
In Stock: {product.inStock}';
$data = ['product' => new Product()];
$result = $tsuku->process($template, $data);
// Output:
// Product: Widget
// Price: $99.99
// In Stock: 1Arrays, Booleans and Numbers
A variable prints its value as a string, the way PHP casts it:
- numbers print as PHP prints them:
29.90becomes29.9- use@number(price, 2)for fixed decimals trueprints1,falseprints nothing- an array prints
Array(and PHP raises an "Array to string conversion" warning) - use@join()or a loop
$template = 'Tags: @join(tags, ", ")
Active: @?{active "yes" : "no"}
Deleted: @?{deleted "yes" : "no"}';
$data = ['tags' => ['sale', 'new'], 'active' => true, 'deleted' => false];
echo $tsuku->process($template, $data);
// Output:
// Tags: sale, new
// Active: yes
// Deleted: noSpecial Characters
Variables can contain data with special characters:
$template = 'Description: {product.description}';
$data = [
'product' => [
'description' => 'A "premium" product & more',
],
];
$result = $tsuku->process($template, $data);
// Output: Description: A "premium" product & moreWARNING
Variables are printed exactly as they are - nothing is escaped automatically. For HTML/XML output, always use escaping functions to prevent XSS:
$template = 'Description: @html(product.description)';
$data = ['product' => ['description' => 'A "premium" product & more']];
// Output: Description: A "premium" product & moreVariable Naming Rules
A variable is a path in curly braces:
- Each name starts with a letter or underscore
- It contains only letters, numbers, and underscores
- Path segments are separated by dots; a segment after a dot may also be a number (
{items.0}) - No spaces inside the braces
camelCase and snake_case both work.
// Valid
{name}
{product_name}
{productName}
{_private}
{item123}
{items.0.name}
// Not a variable - printed literally, no error
{123item} // Can't start with number
{product-name} // No hyphens allowed
{product.name!} // No special chars
{ name } // No spacesBecause anything that is not a valid path stays literal text, JSON, CSS and Magento-style {{widget ...}} directives need no escaping - see Escapes & Special Characters.
Combining with Literals
Mix variables with literal text:
$template = 'Price: ${product.price} USD
SKU: PROD-{product.id}
URL: https://example.com/products/{product.slug}';
$data = [
'product' => [
'price' => 29.99,
'id' => 12345,
'slug' => 'premium-widget',
],
];
$result = $tsuku->process($template, $data);
// Output:
// Price: $29.99 USD
// SKU: PROD-12345
// URL: https://example.com/products/premium-widgetPerformance Tips
- Use direct array access when possible - It's fastest
- Avoid deep nesting - Keep data structures flat where practical
- Cache object results - If calling expensive getter methods repeatedly, consider caching
Next Steps
- Loops → - Iterate over arrays
- Conditionals → - Add logic to templates
- Built-in Functions → - Transform and format data