eZ components - Template component ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. contents:: Table of Contents Template language ================= Basic syntax ------------ The template engine considers blocks, statements embedded in an open and a close curly brace '{ .. }', as code. Everything outside a block is parsed as text. The next example shows a template that does a simple calculation:: 5 times 3 equals: { 5*3 } The sum between the braces will be calculated and printed. The curly braces '{..}' are used in the creation of a template block. Therefore these tags cannot be used directly in plain text anymore. To get around this, there are four options: - Place the braces in a text string. - Escape the curly braces. - Use the {ldelim} and {rdelim} template block. - Use the {literal} tag. Text string ``````````` Place the curly braces in a single quoted or double quoted text string. The text string will then output the curly braces normally:: Draw line: {"{"} (4, 10), (3, 5) {"}"} The output of the line above is: *Draw line: { (4,10), (3, 5) }*. Escape characters ````````````````` A character can be escaped with a backslash (\\). In the text are three characters available that can be escaped. Those are the: - Opening curly brace '{' , - Closing curly brace '}', - Newlines, and - The escape character, backslash itself '\\'. The next example shows how to escape those characters:: Draw line: \{ (4, 10), (3, 5) \} Game path: C:\\Program files\\games\\ Multiple \ lines \ becomes one The output of the template is without the backslash and the characters appear normally:: Draw line: { (4, 10), (3, 5) } Game path: C:\Program files\games\ Multiple lines becomes one {ldelim} and {rdelim} blocks ```````````````````````````` The specialized *ldelim* and *rdelim* blocks can be used to output, respectively, the '{' and '}' characters:: Draw line: {ldelim} (4, 10), (3, 5) {rdelim} The output of the line above is: *Draw line: { (4,10), (3, 5) }*. Using a backslash to escape the curly braces is shorter, but may be more confusing when the backslash is used frequently. Literal tags ```````````` If you want to enter lots of code or text which should not be processed by the template language you can place the code inside *literal* blocks. Any text within this block is read as it is (including back slashes). Text is read until the *{/literal}* is reached:: {literal} Draw line: { (4, 10), (3, 5) } Game path: C:\Program files\games\ {/literal} Comments -------- Comments are text blocks which are stripped away from the output when the template is executed. Comments can be standalone, spanning an entire tag, or placed in-line in template code. Comments are usually used to explain what or why something is done or to comment out code which should no longer be used. The template engine supports three types of comments: - Code comments start and end with, respectively, '{\*' and '\*}' tags. - Multi-line in-line comment, starts with '/\*' and ends with '\*/'. - Single-line in-line comment that starts with '//' and reads until the end of the line or until a closing curly brace '}'. Code comments ````````````` Code comments start and end with, respectively, '{\*' and '\*}' tags. Everything inside is considered as comments:: {* Variable $i alternates the value 0 and 1*} {$i = 1 - $i} {* {if $i == 0} {$i = 1} {else} {$i = 0} {/if} *} Writing only *{$i = 1 - $i}* would have the same output. Multi-line in-line comment `````````````````````````` Multi-line in-line comments are created using \/\* and \*\/. Use this comment to comment a part of a line or comment multiple lines:: {var $a = 1, /*$b = 2, */ $c = 3 } {$a = 2, /* $b = 3, $c = 4 */} If the result after removing the in-line comments is an empty block then the block will be ignored. The next example has an empty block that won't be visible in the output:: { /* var $a = 1 */ } And is of course the same as writing: *{ }*. Single-line in-line comment ``````````````````````````` Single-line in-line comments are created using two slashes: \/\/ . Use this to start a comment which continues to the end of the line or until the closing curly brace '}':: {var $a = 1, // $b = 2, $c = 3} {$a = 4 //, $b = 5, $c = 6} This example declares the variables *$a* and *$c* and assigns in the second statement the value 4 to variable *$a*. Types ----- The template language supports several primitive types: :Boolean: Expresses the truth value, which is either 'true' or 'false'. :Integer: Is a number of the set: { .., -1, 0, 1, .. } :Float: Is a real (floating point) number. :String: A series of characters which are enclosed between single or double quotes. :Array: Contains a set of primitive types. :Object: A PHP object (imported via the user application). Boolean ``````` The boolean type contains either the value: 'true' or the value 'false'. The next example assigns the value 'true' to the variable $isValid:: {var $isValid = true} Some of the operators return also boolean value. For example the '==' operator returns always a boolean value. The Expressions_ section discusses the operators in more detail. The next example uses the '==' operator:: {var $isValid = ($number == 6) } It checks first whether the variable $number is equal to the value 6. The result is either the boolean value 'true' or 'false'. The result is assigned to the variable *$isValid*. Integer ``````` Integers are specified in a decimal notation only. To use octals or hexadimals the number needs to be converted with the appropriate function. Examples are:: {2} {4} {math_hex_to_dec("1F")} See the methods: math_bin_to_dec, math_hex_to_dec, math_oct_to_dec, math_dec_to_bin, ath_dec_to_hex, and math_dec_to_oct. .. Integers can be specified in a decimal, hexadecimal, or octal notation. The .. number itself can be preceded with either a minus or a plus operator. Octal .. numbers start with a zero, and hexadecimal numbers start with '0x' Some .. examples are:: .. .. {2} {// Decimal number} .. {-42} {// Decimal number} .. {+100} {// Decimal number} .. .. {01000} {// Octal number} .. .. {0x1AB} {// Hexadecimal number} Float ````` Floating point numbers are values that contain a real value. Some examples:: {1.0} {-100.234214} {3.14} It is also possible to express an exponent in the float. The exponent is marked with the character 'e' or 'E' followed by one or more digits:: {1.0e3 // 1000 } {2e4 // 20000 } {1e-2 // 0.01 } {0.1e-2 // 0.001} {-3.1e2 // -310 } String `````` The string consist of a series of characters enclosed between single or double quotes:: {'a string' // Using single quotes } {"hello world" // Using double quotes } In the string we use the backslash (\) as escape character. For the single quoted string the escape characters are: +-------------+-------------+ | **String** | **Output** | +-------------+-------------+ | \' | ' | +-------------+-------------+ | \\ \\ | \\ | +-------------+-------------+ | \\ | \\ | +-------------+-------------+ Examples of the single quoted strings are:: {'This string contains a \'quotes\' and backslashes (\\).'} {'A single \ works also.'} {'Characters like \n, \t, ", {, }, $, etc can be used without problems'} The double quoted string allows more special characters than the single quoted string. Most useful escape characters are probably the variables and newlines that can be included in the string. The escape characters for the double quoted strings are: +-------------+-------------------+ | **String** | **Output** | +-------------+-------------------+ | \" | " | +-------------+-------------------+ | \\ \\ | \\ | +-------------+-------------------+ | \\ | \\ | +-------------+-------------------+ | \\n | | +-------------+-------------------+ | \\t | | +-------------+-------------------+ | $ | $ | +-------------+-------------------+ | \\r | | +-------------+-------------------+ The next example inserts newlines in the string:: {"Hello\nHello"} The output of the template above is:: Hello Hello Some other examples of using single and double quoted strings:: {" a \"quoted\" string "} {'Newlines are added with the \\n command.'} {'\tThis string starts with a tab (\\t).'} Array ````` The array is just like in PHP an ordered map. It can be used as an array or as a table that maps values to keys. There are two ways to create an array. The first method has the following syntax:: array( [ key => ] value, [ key2 => ] value2, ... ) The parts between brackets are optional. So the *key* can be omitted. In that case, it would simply create an array. First value has the index 0, the next value has index 1, and so on. The next example creates an array which consists of 3 elements:: {var $names = array( "Bernard", "Manny", "Fran" )} The array values, and in this case the names, can be accessed:: {$names[0] // Outputs "Bernard"} {$names[2] // Outputs "Fran"} {$names[3] // Is not allowed } The array with *keys* maps the key to a value:: {var $personInfo = array( "first_name" => "Bernard", "last_name" => "Black" ) } To access the information:: {$personInfo["first_name"] // Outputs "Bernard"} {$personInfo["last_name"] // Outputs "Black"} The second method to create an array is:: .. This method creates an array that contains the numbers from *number1* to . The next example creates an array with the numbers: 3, 4, 5, 6, and 7. {var $nrs = 3..7 } {$nrs[0] // Outputs 3} This method is especially useful to use in a foreach loop. The following example loops 10 times, and prints the number from 1 until 10:: {foreach 1..10 as $i} Number: {$i} {/foreach} The Foreach_ section describes this loop in more detail. Object `````` Objects are only available when they are sent from the user application. It is not possible to create an object in the template language only. The template language restricts the accessibilities from the object only to its properties; thus function calls are not permitted. The next example is a part of an user application that sends an object to a template:: send->obj = new MyClass; // Create an object and assign it to "obj" $t->process("my_template.ezt"); ?> The class in the example above has two 'magic' PHP functions. Fetching any property is allowed, whereas setting a property value throws an Exception. The template code that belongs to the user application:: {use $obj // Import the "obj" } {$obj->Bernard // Calls the __get method on the object and returns "Hello Bernard"} {$obj->Bernard = "Fran" // Calls the __set method on the object and throws an exception} More information about importing objects is described in the `External variable declaration (use)`_ section. Variables --------- Before a variable can be used for the first time it needs to be declared. A declaration defines a unique name that will be available from now on until the end of the template. The next example declares a local variable with the name the\_answer\_to\_life\_the\_universe\_and\_everything and assigns a value to it:: {* Declare the variable *} {var $the_answer_to_life_the_universe_and_everything} {* Assign the value 42 to it *} {$the_answer_to_life_the_universe_and_everything = 42} Switching the assignment with the declaration results in a compiler error. Variables in the syntax languages are represented by a dollar sign followed by the name of the variable. The variable name is case-sensitive. A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores:: {* valid declarations *} {var $abcdEFG} {var $_hello_} {var $hello12} {* invalid declarations *} {var $12monkeys} {var $dumb&dumber *} The template language has three types of variable declaration: :var: Declares a local variable. (We used this in the previous examples). :use: Imports an external variable. :cycle: Declares a cycle variable. Local variable declaration (var) ```````````````````````````````` The declaration of a local variable creates a variable that has no value from the outside. Outside can be the application that compiles and executes the template. The syntax to declare a local variable is:: {var $ [ = ] [ , $ [ = ] ] } One or multiple variables can be declared with one {var} statement. A value can be assigned to the variable name, directly. If no value is given to the variable, then it will get the default value: null. The next example declares four variables at the same time:: {var $a = 2, $b = "Hello World", $c = true, $d} External variable declaration (use) ``````````````````````````````````` The declaration of an external variable creates a variable that usually has a value from the outside (user application). The syntax for this type of variable is as follows:: {use $ [ = ] [ , $ [ = ] ] } As you can see, the only difference with the local variable declaration is the tag 'use'. The variable will be imported from the application and can be used in the template. If the imported variable name is not assigned to a value then it will get the default value from the assignment. One of the reasons that a variable has no value is that the variable is not made available by the user application. The next example shows a part of the user application, using the template engine:: $a = 1; $b = 2; $c = 3; $t = new ezcTemplate(); // Send some information to the Template $t->send->firstname = "Bernard" $t->send->lastname = "Black"; $t->send->age = 31; // Process the template and echo it. echo $t->process(); The variables: $username, $nickname, and $age can be 'used' by the template:: {use $firstname = "unknown", $lastname = "unknown"} {use $age = 0, $length = 0} {$firstname} {$lastname} his/her age is: {$age} The variable $length (if it was used) will get the value 0, because the user application does not assign a value to it. More information about importing variables is described in the Include_ section. Cycles `````` A cycle is a special type of variable that contains a set of values. The cycle variable should always be assigned to an array. Retrieving a value from the cycle is one array element at the time. Specific control structures are available to cycle through the set of values. The syntax for the cycle is:: {cycle $ [ = ] [ , $ [ = ] ] } An array must be assigned to the cycle variable. Otherwise the template compiler *may* give a compiler error. (Sometimes it is not possible to know at compile time whether the assignment is an array or not.) The next example declares a cycle, assigns a value, and retrieves the first and second value:: {cycle $rgb = array( "red", "green", "blue" ) } {$rgb // Print "red"} {$rgb // Print "red" again} {increment $rgb // Go to the next element in the set} {$rgb // Print "green"} See the Increment_, Decrement_ and Reset_ section for more information. Scopes `````` Variable declarations must be done at the highest scope of the template. Declaring a variable in a lower scope will result in a compiler error. Scopes are usually opened and closed with a start and end template block. Template blocks that open a new scope are: {if .. }{/if}, {while ..} {/while}, {foreach ..} {/foreach}, {switch .. } {/switch}, etc. The next example demonstrates this scoping:: {var $a = 2 // Correct } {if 2 == 3} {* This opens a new scope *} {var $b // ERROR! } {/if} Returning variables ``````````````````` Templates itself can also return variables to the user application or other templates. The return statement defines the variables that need to be returned:: {return ( as | ) [, ( as | ), ... ] } The return statement returns one or multiple variables. The caller of the template can retrieve the return values. Consider the following template:: {* Return 6! and "Hello world" *} {var $fac6 = 6 * 5 * 4 * 3 * 2 } {return $fac6, "Hello world" as $helloWorld} The user application can retrieve these values via the receive property of the template. See the next example for a demonstration:: $t = new ezcTemplate(); // Process the template. $t->process(); // Retrieve the values from the return. $fac6 = $t->receive->fac6; $hw = $t->receive->helloWorld; // Output Hello world: echo $hw; More information about returning variables is described in the Include_ section. Expressions ----------- An expression is anything you write in a template block that doesn't start with a special tag. But expressions are also used in template blocks with a tag and gives merely a value. PHP quotes the expression as "Anything that gives a value", that is also true for the template syntax. Expressions can be a single *operands* that returns a value. It is also possible to combine multiple operands with *operators*. The value returned depends on the used operands and operators. The operands are: - Boolean_ - Integer_ - Float_ - String_ - Array_ - Variables_ - Functions_ The operands Boolean, Integer, Float, String, and Array are described in the Types_ section. Variables are described in the Variables_ section. Functions will be described in the Functions_ section. Variables and functions are considered as operands since they return one value. The type of this return value is also a: Boolean, Integer, Float, String, or Array. An operand returns a single value. Some examples are:: {5} {"Hello"} {str_len("Hello")} The values returned are, respectively: 5, Hello, and 5. Operators are things that you feed with one or multiple values and will result another value. Examples of operators are adding two numbers together with the plus (+) operator. This operator expects two integers or floats (in any combination) and returns either a integer of float. Another example is the equal operator (==). It expects two types operands of the same type and returns a Boolean. Arithmetic operators ```````````````````` The arithmetic operators can be used on all expressions which return a numerical value. The operator itself returns also a numeric value. The table below describes the available arithmetic operators: ============== =========== Negation -$o Ignored +$o Addition $ol + $or Subtraction $ol - $or Multiplication $ol * $or Division $ol / $or Modulus $ol % $or ============== =========== Note: The negation in this table is the arithmetic negation. Don't confuse this with the logic negation. The unary plus operator can also be used, but it doesn't affect the value. It's usually used to clarify that it's not a negative value. Examples:: { 2 + 5 // Returns value 7} { 2 - 5 } { 4 + 3 * 2 // Due to the operator precedence, first the * // will be evaluated and thereafter the +. } {var $a = 2} {var $b = -$a} Comparison operators ```````````````````` All comparison operators return a boolean value. The left-hand side and right-hand side should be of the same type. The available comparison operators are: ===================== ============ Equal $ol == $or Identical $ol === $or Not equal $ol != $or Not identical $ol !== $or Less than $ol < $or Greater than $ol > $or Less than or equal $ol <= $or Greater than or equal $ol >= $or ===================== ============ Examples:: { 4 == 5 } { 2 <= 5 } { true != false } { 4 == 5 == 6 } The last example compares 4 with 5. This returns the boolean *false*. After the first step the comparison is:: { false == 6 } The number 6 will be changed into a boolean. Every number except zero will get the boolean value *true*. Basically the last step of the comparison is:: { false == true } And this return the boolean value *false*. Logical operators ````````````````` The logical operators are used on all expressions which return a boolean value. The operator returns also a boolean: === ========== Not ! $o And $ol && $or Or $ol || $or === ========== Some usage examples:: { true || false } { $a == 5 && $a != 7 } { $a || $b } Assignments ----------- Assignments set a value to a variable. If the variable does already contain a value, it will be overwritten. As explained in the Variables_ section the variable must be declared first. Notice that an assignment can be used in the declaration itself. The syntax language has two types of assignments. The former type assigns a new value to the variable:: { = } The expression is evaluated and assigned to the variable. The next example assigns the value 4 to the variable *$myVar*:: {var $myVar} { $myVar = 3 + 5 / 5 } The latter assignment type updates the existing value with a modifier. There are multiple operators available: ============== =========== Addition $var += $or Subtraction $var -= $or Multiplication $var \*= $or Division $var /= $or Modulus $var %= $or Pre increment ++$var Pre decrement --$var Post increment $var++ Post decrement $var-- ============== =========== The Addition, Subtraction, Multiplication, Division, and Modulus assignment operators do an arithmetic calculation between the left (variable) and the right operand (expression) and assigns the value in the left operand (variable) again. Notice that the variable must already contain a value. The increment operators increment the number of the current variable by one. The decrement operators do the opposite and decrement the value of the current variable by one. There is no difference between the pre and post operators, and both are present for convenience purposes. Examples:: {var $myVar = 5 } {$myVar += 5 // $myVar has the value 10 } {$myVar++ // is the same as $myVar += 1 } {$myVar *= 10 // Multiply with 10} {--$myVar // Same as: $myVar -= 1 } Functions --------- The template language has lots of build-in functions that can be called. These functions are categorized in a few groups: String, Array, Regular expression, Type information, and Arithmetic (math) functions. The functions are explained in the appendix. A function call has the following syntax:: ( [ Parameter1 [, Parameter2, ... ] ] ) An example:: {var $res = str_compare( "Hello", "Blaat" ) } {$res // Contains false} All template functions follow these rules: - Function output is always returned. No variables are changed via references. - If the function contains a "haystack" and a "needle" then the first parameter will be the "haystack". The "needle parameter is a parameter that operates on another parameter, the "haystack". Contexts -------- The purpose of the context is simplify the development of the templates and make the templates more secure. The Context defines the purpose of the template output. For example the XHTML Context should be set for the templates that generate (X)HTML output. When a template is processed and executed, it runs with a specific context. By default the context is set to XHTML, but it can also be specified manually. The next example shows a part of a user application that specifies the XHTML context:: $config = ezcTemplateConfiguration::getInstance(); $config->context = new ezcTemplateXhtmlContext(); $t = new ezcTemplate(); $t->process( "hello_world.ezt" ); Configuring the Template engine is discussed in the tutorial in more detail. The available context are described in the next subsections. XHTML Context ````````````` The XHTML Context escapes the HTML characters from the output from the expression blocks. Output outside the blocks are not escaped. See the next example:: {var $lt = "3 < 5"} {$lt} This template contains the HTML character '<' in an expression block. This character will be escaped. The output of the template is:: 3 < 5 The escape characters of the XHTML context are: ========= =========== Character Translation ========= =========== & & " " < < > > ========= =========== If the HTML characters in the expression block should not be escaped then the "raw" block should be used. The next example demonstrates a "raw" block:: {var $myBoldText = "Hello world} {raw $myBoldText} This template outputs:: Hello world See the Raw_ section for more information. No Context `````````` The No Context does not escape any characters. This context is available merely for testing purposes. Control structures ------------------ Control structures are elements which help you control the flow of the code, either by doing conditional statements or by repeating certain actions. Increment ````````` The increment construct sets the cycle variable to the next value in the cycle array:: {cycle $rgb = array("red", "green", "blue" )} {$rgb // Print "red" } {increment $rgb} {$rgb // Print "green" } If the end of the cycle array is reached, it will jump again to the first value of the array. Decrement ````````` The decrement construct sets the cycle variable to the previous value in the cycle array:: {cycle $rgb = array("red", "green", "blue" )} {$rgb // Print "red" } {decrement $rgb} {$rgb // Print "blue" } If the begin of the cycle array is reached, it will jump again to the last value of the array. Reset ````` The reset construct sets the cycle variable to the first value in the cycle array:: {cycle $rgb = array("red", "green", "blue" )} {$rgb // Print "red" } {increment $rgb} {$rgb // Print "blue" } {reset $rgb} {$rgb // Print "red" } If, else, elseif ```````````````` The *if* construct allows conditional execution of code fragments. The structure is:: {if } {/if} If the evaluates to true, the fragment will be executed. For instance the following code will show "$a is less than $b" if $a is less than $b:: {if $a < $b } $a is less than $b. {/if} The *else* construct can be used in an *if* statement. It contains a code fragment that will be executed if the evaluates to false:: {if } {else} {/if} The is executed when the expression is false. Otherwise is executed. The next example outputs "$a does not contain the value 5!" if the expression doesn't match:: {if $a == 5} $a contains the value 5! {else} $a does not contain the value 5! {/if} The *elseif* construct can also be used in an *if* statement:: {if $weekday == 0} Monday {elseif $weekday == 1} Tuesday {elseif $weekday == 2} Wednesday {else} Thursday, Friday, Saturday, or Sunday. {/if} Writing directly an *elseif* statement is the same as writing them with separate *if* and *else* statements:: {if $weekday == 0} Monday {else} {if $weekday == 1} Tuesday {else} {if $weekday == 2} Wednesday {else} Thursday, Friday, Saturday, or Sunday. {/if} {/if} {/if} As you can see, this makes the code harder to read. Switch, Case, Default ````````````````````` The switch construct is quite similar to multiple *if* and *elseif* statements. The syntax is as follows:: {switch } [ case2 [ case3, .. ] ] [ default ] {/switch} The case blocks:: {case [, , ..]} {/case} And the default:: {default} {/default} The switch statement expects an expression. This expression will then be compared with the literal values from the *case* statements. The comparison starts and goes to the next literal as the values from the and are not equal. The from the first match will be executed and the rest of the cases are skipped. If none of the cases match, then the default block will be executed. See the example switch statement below:: {switch $weekDay} {case 0} Monday {/case} {case 1} Tuesday {/case} {case 2} Wednesday {/case} {case 3, 4, 5, 6} Thursday, Friday, Saturday, or Sunday {/case} {default} The $weekDay should be a number between 0 and 6. {/default} {/switch} This switch converts the weekday number to a name. Foreach ``````` A very important construct in the template language is the *foreach*. The foreach is a loop structure that iterates over an array. Since this loop is used so often in the templates, it has several convenience tags build in. First we'll show the basic syntax:: {foreach as } {/foreach} {foreach as => } {/foreach} Two foreach structures are shown. The first structure takes each element from the and assigns it to the variable . The second structure does the same, except that the key of the array is assigned to the variable . An example for each structure:: {var $rgb = array( "red", "green", "blue" ) } {foreach $rgb as $color} The color is: {$color} {/foreach} {foreach $rgb as $key => $color} Array key {$key} contains the color: {$color} {/foreach} The output for this example will be:: The color is: red The color is: green The color is: blue Array key 0 contains the color: red Array key 1 contains the color: green Array key 2 contains the color: blue With this syntax we can easily loop any number, and is more convenient than using the while_ structure. This is demonstrated next:: {foreach 1..10 as $i} Iteration {$i} {/foreach} This works of course because the "1..10" statement creates an array with the values from 1 until 10. Often a foreach is used to create some kind of table or list. Several extensions are made available to ease the development: :Cycles: Increments or decrements a cycle variable. :Offset: Start the loop at a given offset. :Limit: Limits the number of iterations. The foreach loop can have an increment and decrement tag. These tags increment and/or decrement an cycle value, and work exactly the same as the Increment_ and Decrement_ control structures. The syntax is almost the same in the foreach:: [increment [, variable2, ... ] ] [decrement [, variable2, ... ] ] These tags are the same as the Increment_ and Decrement_ control structures. This tag is added at the end of the foreach construct. The next example increments the cycle value in every iteration of the loop:: {cycle $blackAndWhite = array( '#00000', '#FFFFFF' )} {foreach 1..5 as $value increment $blackAndWhite} Number: {$value} {/foreach} This loop outputs the following code:: Number: 1 Number: 2 Number: 3 Number: 4 Number: 5 The offset and limit code constructs are specified after the cycle increment or decrement tag. The offset and limit constructs are extremely useful for splitting a long table or list over multiple page views. The next example demonstrates this:: {use $hugeArray = array(), $offset = 0} {foreach $hugeArray as $tableEntry offset $offset limit 100} {* Show the information from the $tableEntry *} {foreach} See the `External variable declaration (use)`_ section for more information. The loop will start at the $offset and won't show the previous elements. The maximum iterations of the loop is 100. Another example shows the numbers from 50 until 100:: {var $hugeArray = 1..1000} {foreach $hugeArray as $value offset 50 limit 50} {$value} {/foreach} While ````` The while loop loops over a code fragment as long as the expression in the while evaluates to true. The syntax of the while loop is as follows:: {while } {/while} Usually the expression evaluates whether a counter reaches a certain number. In the the counter in increased or decreased:: {var $i = 0} {while $i < 10} The number is: {$i}. {$i++} {/while} This example prints the numbers from 0 until 9. If you write a while loop, make sure that the loop eventually ends. The next example demonstrates another while loop. This loop increments a value from a Cycle. Compare how the same example can be done with a Foreach_:: {cycle $blackAndWhite = array( '#00000', '#FFFFFF' )} {var $i = 1} {while $i <= 5 } Number: {$i} {$i++} {increment $blackAndWhite} {/while} Delimiter ````````` The delimiter can be used (only) inside a loop to do every given iteration a specific action. The syntax is as follows:: {delimiter [modulo [is ]]} {/delimiter} The "module..." part can be omitted and by default the delimiter will be inserted between every iteration of the loop. If a modulo is used, the "is " part of the delimiter can be omitted and will be interpreted as "is 0". The delimiter will always be executed between two iterations of the loop. In the next example between every name a comma is inserted:: {var $names = array( 'Bernard', 'Fran', 'Manny' )} {foreach $names as $name} {$name} {delimiter}, {/delimiter} {/foreach} The next example demonstrates creates a matrix with 4 rows and 4 columns. The delimiter closes the current row and opens a new one every forth column as the delimiter is only added when "internal counter modulo 4" equals 0. The "internal counter" simply counts the number of executed iterations:: {var $columns = 4} {foreach 1..16 as $nr} {delimiter modulo $columns} {/delimiter} {/foreach} Continue ```````` The continue statement is used within the looping structures to skip the rest of the current loop iteration and continue execution at the condition evaluation and then the beginning of the next iteration. If a delimiter is available in the looping structure then this delimiter will be added. Use the Skip_ statement to skip also the delimiter. The next example show the numbers 1 to 5 separated with a comma. After the numbers 1, 2, and 3 is the word "beer" appended. As the example shows, the numbers higher than 3 will not execute the rest of the foreach anymore. The delimiter is added anyway:: {foreach 1..5 as $i} {delimiter} , {/delimiter} {$i} {if $i > 3} {continue} {/if} beer {/foreach} The output of the template is:: 1 beer, 2 beer, 3 beer, 4 , 5 Skip ```` The skip is the same as a continue, except that the delimiter in the loop will be skipped also. The next example show the numbers 1 to 5. The number 1, 2, and 3 have the word "beer" appended and are separated with a comma. As the example shows, the numbers higher than 3 will not execute the rest of the foreach anymore and the delimiter is not appended:: {foreach 1..5 as $i} {delimiter} , {/delimiter} {$i} {if $i > 3} {skip} {/if} beer {/foreach} And outputs:: 1 beer, 2 beer, 3 beer 4 5 Break ````` The break ends execution of the current foreach or while structure. The example below prints the numbers 1 and 2. Due to the break, the rest of the loop is skipped:: {foreach 1..10 as $i} {$i} {if $i == 2} {break} {/if} {/foreach} Include ``````` The include calls other templates which will be executed within the current template. Variables can be passed on and retrieved from the included template. The generic template could then be used at multiple places and is configurable via the given variables. The syntax of the include is as follows:: {include [ send ] [ receive ] The has this syntax:: as | And the has almost the same syntax as the :: as | A next example will clarify the syntax a bit more:: {include "calc_a_plus_b.ezt" send 2 as $a, 5 as $b receive $c as $sum } The included template calculates the sum of the given variables $a and $b, and returns the answer in variable $c. The expressions "2" and "5" are assigned to the variables $a and $b of the included template. The value of the (returned) variable $c is directly assigned to the variable $sum. The variable $sum does not need to be declared first. The template "calc\_a\_plus\_b.ezt" is:: {use $a = false, $b = false} {if $a === false || $b === false} Variable $a or $b has an incorrect value. {/if} {return $a + $b as $c} The next templates includes the "calc\_a\_plus\_b.ezt" but does not use the expression part of the include:: {var $a = 2, $b = 5} {include "calc_a_plus_b.ezt" send $a, $b receive $c } {var $sum = $c} Raw ``` The raw construct outputs raw information and is not affected by the Contexts_. For example, the XHTML context is set and an expression contains HTML characters (which should be sent to the output) then use the "raw" block:: {var $myBoldText = "Hello world"} {raw $myBoldText} This template outputs:: Hello world Extensions ========== This section explains how you can extend your template language. Extending the template language gives you the opportunity to add more application specific functionality. Some examples of template language extensions are: - Adding a method to fetch information from a data structure. This data structure could be a single or a group of objects, a database, an array, etc. - Creating an HTML table using your own customized template blocks. - Doing an application specific calculation. Currently, there are two ways of adding custom functionality to the template. The methods are named: **custom blocks** and **custom functions**. Together we call them **custom extensions**. First, we'll explain how to create a custom block. With the knowledge of these custom blocks, we explain - much shorter - the custom functions. Custom blocks ------------- Custom blocks (and custom functions) are used in the template language and implemented in PHP. We take a look at the template language, first. When it is clear how custom blocks are used, we explain how to add a custom block using PHP. Custom blocks in the template language `````````````````````````````````````` Custom blocks add specific behavior to the template language. The most basic structure of a custom block - without any parameters - is:: '{' '}' The block starts and ends with curly braces. The ** identifies the custom block. Optionally, a custom block has also a closing block:: '{' '/' '}' The name is the same as the start block, but starts with a forward slash ('/'). The text between the open and close tag is considered as input data. Whether a custom block should have a close tag is up to the developer. The next example demonstrates a custom block with an open and close tag that capitalizes the text in between:: {capitalize} Guybrush Threepwood. {/capitalize} Another example that uses a custom block without a close tag:: {capitalize "Guybrush Threepwood."} Whether or not a custom block has a close tag, it handles the parameters the same. The structure of a custom block is as follows:: '{' block_name [start_expression] [ ['='] ... ] '}' Basically, it describes that a custom block can have: - One optional expression which is not bound to a parameter name. - Zero or more named parameters with a value. Between the parameter name and value is an optional equal sign. Some example blocks which uses parameters:: {link "eZ systems" to "http://ez.no"} {table border=true bgcolor="red"} {debug} {calculate 5 plus 5} {join array( 'Hello', "world" ) with "_"} Note that the values used in the examples are just ordinary expressions. Therefore it also possible to write:: {link "eZ" . " systems" to 'http'. "://" . "ez.no"} {calculate 2 + 3 plus 1 * 2 + 3} Again, the optional and required parameters are up to the developer. Adding a new custom block ````````````````````````` New custom blocks are added to the template engine with the ezcTemplateConfiguration::addExtension() method. This method expects the class name which implements the new custom block. The next example adds a custom block to the template engine which is implemented in MyClass:: $config = ezcTemplateConfiguration::getInstance(); $config->addExtension( "MyClass" ); The custom block class should implement the ezcTemplateCustomExtension interface. This interface has only one method getCustomBlockDefinition(). The class implementing this method should return an ezcTemplateCustomBlockDefinition object from a given block name, if possible. Custom block definition ``````````````````````` The custom block definition describes how the template engine should interpret the custom block. The information is provided by returning an instance of the ezcTemplateCustomBlockDefinition:: class ezcTemplateCustomBlockDefinition extends ezcTemplateCustomExtension { public $class; public $method; public $hasCloseTag; public $startExpressionName; public $optionalParameters = array(); public $requiredParameters = array(); } The member variables that should be set in this class are: :class: String value that specifies the (static) class that implements the function to be executed. :method: String value that specifies the (static) method that should be run. :hasCloseTag: Boolean value that specifies whether the class has an open and close tag or only a open tag. :startExpressionName: The first parameter of a custom block without a name is called the start expression. If the custom block should have a start expression then this variable specifies a name for it. The name should reappear in either the optionalParameters or the requiredParameters. :optionalParameters: Optional named parameters for this custom block. :requiredParameters: Required named parameters for this custom block. The following custom block creates a hyper-link from a name and an URL:: {link "name" to "url" [title "title"]} This custom block has a: - Required unnamed parameter that contains the name. - Required named parameter "to" that contains the URL. - Optional named parameter "title" that contains the title. Except for the class and the method name the CustomBlockDefinition should look like:: $def = new ezcTemplateCustomBlockDefinition; $def->class = "MyLink" $def->method = "linkMethod" $def->hasCloseTag = false; $def->startExpressionName = "from"; $def->optionalParameters = array( "title" ); $def->requiredParameters = array( "from", "to" ); The CB definition should be made available to the template engine via a class implementing the ezcTemplateCustomBlock interface:: interface ezcTemplateCustomBlock { public static function getCustomBlockDefinition( $name ); } The class implementing the getCustomBlockDefinition() method should return an ezcTemplateCustomBlockDefinition for the given block name $name. The next code demonstrates a class that implements the interface:: class MyLink implements ezcTemplateCustomBlock { public static function getCustomBlockDefinition( $name ) { switch ($name ) { case "link": $def = new ezcTemplateCustomBlockDefinition; $def->class = "MyLink"; // // Create definition return $def; } return false; } } Handling the custom block ````````````````````````` In the CB definition is specified which class and what method should produce the custom block output. A typical implementation to create a hyper-link would be:: public static function link( $parameters ) { $title = ""; if( isset( $parameters["title"] ) ) { $title = "title='". $parameters["title"] ."'"; } return "".$parameters["from"]."" } The method implementing the custom block returns a string that will be inserted in the template output. The custom block parameters are provided in the first parameter as an array. The method itself must check whether the optional parameters are sent or not. Required parameters are always available as the template compiler throws a compiler exception if these parameters are absent. The custom blocks that do have a close tag need a method that accepts two parameters. For example the following custom block has a close tag:: {capitalize} Guybrush Threepwood {/capitalize} The method that implements the custom block:: public static function capitalize( $parameters, $text ) { return strtoupper( $text ); } The $parameters parameter is never used. The text between the open and close tag of the custom block is always passed in the second parameter. Example ``````` The 'calc' custom block calculates the sum of the given values. The sum is calculated from the initial value plus or minus the values added to the "plus" and or "minus" parameter. Some usage examples are:: {calc 5 plus 3} {calc 5 plus array(2,5,2) minus 2} {calc 2 minus 5} The custom block could be implemented like:: class CalcCustomBlock implements ezcTemplateCustomBlock { public static function getCustomBlockDefinition( $name ) { switch ($name ) { case "calc": $def = new ezcTemplateCustomBlockDefinition; $def->class = __CLASS__; $def->method = "calculate"; $def->hasCloseTag = false; $def->startExpressionName = "init"; $def->requiredParameters = array("init"); $def->optionalParameters = array("plus", "minus"); return $def; } return false; } public static function calculate( $params ) { $result = $params["init"]; if ( isset( $params["plus"] ) ) { if( is_array( $params["plus"] ) ) { foreach( $params["plus"] as $value ) { result += $value; } } else { $result += $params["plus"]; } } if ( isset( $params["minus"] ) ) { if( is_array( $params["minus"] ) ) { foreach( $params["minus"] as $value ) { result -= $value; } } else { $result -= $params["minus"]; } } return $result; } } This new custom block needs to be assigned to the Template configuration:: $config = ezcTemplateConfiguration::getInstance(); $config->addExtension( "CalcCustomBlock" ); And of course the template can be run like:: $t = new ezcTemplate(); $t->process( "my_template.ezt" ); Custom functions ---------------- This section explains how the custom function can be implemented. Custom blocks and custom functions are very similar. Therefore we explain the custom functions much shorter. Custom functions in the template language ````````````````````````````````````````` Custom functions are extra functions that can be used in the Template expressions. Some (mathematical) examples are:: Greatest common divisor: {gcd(8, 12)} {sin( $angle ) * 2} { matrix_multiply( $m1, $m2) } Basically, the second line in the example runs a custom function and multiplies the result with two. This demonstrates that the difference between a custom block and a custom function. Custom functions can be used within an expression. Custom blocks are directly generating an output result. Adding a new custom function ```````````````````````````` As with the custom block, custom functions are added to the template engine by the ezcTemplateConfiguration::addExtension() method. The class name given to this method should implement the ezcTemplateCustomFunctionDefinition. Notice that this is the same as adding a custom block. :: $config = ezcTemplateConfiguration::getInstance(); $config->addExtension( "MyClass" ); The example above adds *MyClass* to the ezcTemplateConfiguration. MyClass implements the ezcTemplateCustomFunctionDefinition:: class ezcTemplateCustomFunctionDefinition extends ezcTemplateCustomExtension { public $class; public $method; public $parameters = array(); } The $class and $method parameter are the same as for custom blocks. The $parameters member variable specifies the required and optional parameters for the custom function. - Required parameters are named strings. - Optional parameters are named strings enclosed with square brackets. These parameters should be specified after the required parameters. As with functions in PHP the order of the parameters matter. The next example demonstrates a complete custom function implementation:: class MyClass implements ezcTemplateCustomFunction { public static function getCustomFunctionDefinition( $name ) { switch ($name ) { case "func": $def = new ezcTemplateCustomBlockDefinition; $def->class = "MyClass"; $def->method = "customFunction"; $def->parameters = array( "reqParam", "anotherReqParam", "[optionalParam]"); return $def; } return false; } public static function customFunction( $firstParam, $secondParam, $thirdParm = "isOptional" ) { // Implementation. return "string"; } } The custom parameters specified in the definition block should also be present in the *customFunction* implementation. Three parameters are specified, so the customFunction implementation should have three parameters. The last parameter in the parameter definition is specified as optional, so should the last parameter in customFunction be optional. The interface of the ezcTemplateCustomFunction requires to implement getCustomFunctionDefinition:: interface ezcTemplateCustomFunction { public static function getCustomBlockDefinition( $name ); } .. .. Properties .. ---------- .. .. Use .. ^^^ .. The nodes: $node and $optionalNode come from the application, and need therefore be known in the template code. .. If the $optionalNode is not set, it will get the default value "false":: .. .. {use $node, $optionalNode = false} .. .. .. Accessing a property .. ^^^^^^^^^^^^^^^^^^^^ .. :: .. .. {use $node, $optionalNode = false} .. .. Impressive title: {$node->impressiveTitle} .. .. Norwegian title: {$node->titles["norwegian"]} .. .. {if $optionalNode != false} .. Extra title: {$optionalNode->titles["norwegian"]} .. {/if} .. .. Local Variables: mode: rst fill-column: 79 End: vim: et syn=rst tw=79
{$nr}