Lesson 7.5: A template operator
A template operator is the smallest useful extension: a new word for templates, such as |mysite_initials. It is
also the best first piece of PHP for template builders, because its input and output are plain values. In this
lesson learners write, register and use an operator with one optional parameter, and compare their hand-written
version with the RAD wizard.
At a glance
| Course | Developers |
| Module | Module 7: Extensions |
| Duration | 55 minutes (15 presenting, 40 exercise) |
| Level | Intermediate |
| Audience | Developers |
| Prerequisites | Lesson 7.3; Lesson 2.4 |
Learning objectives
After this lesson, learners can:
- write an operator class with
operatorList(),namedParameterPerOperator(),namedParameterList()andmodify(); - give every optional parameter a default value;
- register the operator in
autoloads/eztemplateautoload.phpand[TemplateSettings] ExtensionAutoloadPath[]; - use the operator in pipe form and with a parameter;
- find the RAD wizard that writes operators.
Trainer's notes
How to present it
Sources: a real operator extension, extension/str_replace/ (if installed), the template operator warning in
Templates and design, part 7,
and RAD tools.
- The registration (3 minutes).
autoloads/eztemplateautoload.phpfills$eZTemplateOperatorArray[]with thescript, theclassand theoperator_names. The extension'ssettings/site.ini.append.phpadds[TemplateSettings] ExtensionAutoloadPath[]=<extension>so the kernel reads that file. - The class (6 minutes). Walk through the exercise's class:
operatorList()names the operators;namedParameterPerOperator()returnstrue;namedParameterList()lists each parameter withtype,requiredanddefault;modify()receives the value on the left of the pipe in$operatorValue(by reference) and the parameters in$namedParameters, and replaces$operatorValuewith the result. - Defaults (2 minutes). A parameter without a default that a template leaves out arrives as
null, and the debug output warns "Operator '...' has no default value for parameter '...'". - Escaping (2 minutes). An operator returns a value; the template washes it when it prints it. Do not return HTML from an operator unless that is its job, and then escape inside.
- The wizard (2 minutes). Setup > RAD, the template extension wizard (
/setup/templateoperator), writes operators, fetch functions and template functions as a complete extension.
Common questions
Can it be called in function form? This operator reads the value on the left of the pipe, so write
{$name|mysite_initials}. An operator that should also work as {my_operator( $value )} takes the value as a
parameter too and uses it when given, as str_replace's subject parameter does.
Can one class hold several operators? Yes: list them in operatorList() and operator_names, and switch on
$operatorName in modify().
Is an operator compiled into the template cache? Its call is; the operator runs every time the compiled template runs, unless it declares hints for compile-time evaluation. Keep operators fast.
Pitfalls
- Forgetting
ExtensionAutoloadPath[]. The operator is unknown and the debug output says so. - Not clearing caches. After registering, clear the
iniandtemplatecaches. - Prefix. Operator names are global to all templates; prefix them (
mysite_) to avoid clashes.
Hands-on exercise
On the development installation, in extension/mysite_hello.
Create
autoloads/mysitehellooperators.php:/** * Template operators of mysite_hello: {$text|mysite_initials} and {$text|mysite_initials( '-' )} */ class mysiteHelloOperators { public function operatorList() { return array( 'mysite_initials' ); } public function namedParameterPerOperator() { return true; } public function namedParameterList() { return array( 'mysite_initials' => array( 'separator' => array( 'type' => 'string', 'required' => false, 'default' => '' ) ) ); } public function modify( $tpl, $operatorName, $operatorParameters, $rootNamespace, $currentNamespace, &$operatorValue, $namedParameters ) { if ( $operatorName === 'mysite_initials' ) { $initials = array(); foreach ( preg_split( '/\s+/u', trim( (string)$operatorValue ) ) as $word ) { if ( $word !== '' ) $initials[] = mb_strtoupper( mb_substr( $word, 0, 1 ) ); } $operatorValue = implode( $namedParameters['separator'], $initials ); } } }Create
autoloads/eztemplateautoload.php:$eZTemplateOperatorArray = array(); $eZTemplateOperatorArray[] = array( 'script' => 'extension/mysite_hello/autoloads/mysitehellooperators.php', 'class' => 'mysiteHelloOperators', 'operator_names' => array( 'mysite_initials' ) );Register the autoload path:
php bin/php/console exp:ini add site.ini/TemplateSettings/ExtensionAutoloadPath mysite_hello extension:mysite_hello.Check both PHP files with
php -l; clear theiniandtemplatecaches.In the playground, use the operator:
['Ada Lovelace'|mysite_initials] ['grace brewster hopper'|mysite_initials( '.' )] [$node.name|mysite_initials|wash]Remove
'default' => ''from the parameter definition, clear the template cache, run the playground with--debug=warning, and read the warning. Put the default back.Use the operator in
greet.tplof lesson 6.2:<p>Initials: {$name|mysite_initials|wash}</p>, and open the view.Open Setup > RAD and find the template extension wizard; compare the files it lists with yours.
Commit the files.
Expected result
- Step 5 prints
[AL] [G.B.H]and the initials of node 2's name. - Step 6: the warning "Operator 'mysite_initials' has no default value for parameter 'separator'", followed by
(compiling <template>)because the template was compiled anew. - Step 7: the greeting page shows the initials.
- The trainer checks one learner's playground output.
Quiz
- Which file registers an extension's template operators?
- Which setting makes the kernel read that file?
A.
ActiveExtensions[]B.ExtensionAutoloadPath[]C.DesignExtensions[]D.ExtensionRepositories[] - In
modify(), where is the value on the left of the pipe, and how is the result returned? - What happens when a parameter has no default and a template leaves it out?
- Why prefix operator names?
Answers
autoloads/eztemplateautoload.phpof the extension.- B.
[TemplateSettings] ExtensionAutoloadPath[]. - In
$operatorValue, passed by reference; the method replaces it with the result. - The operator gets
null, and the debug output warns once per operator and parameter. - Operator names are shared by all templates of the installation; a prefix avoids clashes.
Further reading
- Template operators in a theme.
- Templates and design, part 7: the warning for missing defaults.
- RAD tools: the template extension wizard.
Related pages
- Module 7: Extensions
- Developers: course overview
- Trainers: start here
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.