Contents

  • 1 Dwoo Documentation Wiki
    • 1.1 A bit of history
    • 1.2 Developers Documentation
      • 1.2.1 Dwoo users :
      • 1.2.2 Smarty user ?
    • 1.3 Designers Documentation
    • 1.4 Other Resources
    • 1.5 Quick Links
    • 1.6 Stuff

[edit] Dwoo Documentation Wiki

[edit] A bit of history

Dwoo is a PHP5 Template Engine that was started in early 2008. The idea came from the fact that Smarty, a well known template engine, is getting older and older. It carries the weight of it's age, having old features that are inconsistent compared to newer ones, being written for PHP4 its Object Oriented aspect doesn't take advantage of PHP5's more advanced features in the area, etc. Hence Dwoo was born, hoping to provide a more up to date and stronger engine. So far it has proven to be faster than Smarty in many areas, and it provides a compatibility layer to allow developers that have been using Smarty for years to switch their application over to Dwoo progressively.

If you need offline access to this wiki you can download it as a chm file.

[edit] Developers Documentation

[edit] Dwoo users :

  • Getting Started
    • Using Dwoo with your framework of choice
  • API Docs - Learn the ins and outs of Dwoo's classes
  • Extending - How to write plugins

[edit] Smarty user ?

  • Using the Smarty Adapter to convert your Smarty code
  • Smarty Migration Guide
  • List of unsupported Smarty features

[edit] Designers Documentation

  • Syntax
  • Plugins

[edit] Other Resources

  • Download Dwoo
  • Dwoo Homepage
  • Dwoo Forums
  • Code Coverage Report
  • Auto-Generated API Docs
  • Dwoo syntax file for GeSHi

[edit] Quick Links

  • List of $dwoo and other reserved variables
  • List of iterator variables (loop, for and foreach)
  • Shortened syntax for power users
  • About scope usage

[edit] Stuff

  • Dwoo Users / Sites built with it


Contents

  • 1 Running Dwoo
    • 1.1 Dwoo at it's simplest
    • 1.2 Using Template and Data objects
    • 1.3 Using a Compiler object
    • 1.4 Using Dwoo with loops - Blog example

[edit] Running Dwoo

[edit] Dwoo at it's simplest

Here is the simplest way to output a Dwoo template.

<?php

// Include the main class, the rest will be automatically loaded
include 'path/to/dwooAutoload.php';

// Create the controller, it is reusable and can render multiple templates
$dwoo = new Dwoo();

// Create some data
$data = array('a'=>5, 'b'=>6);

// Output the result ...
$dwoo->output('path/to/index.tpl', $data);
// ... or get it to use it somewhere else
$dwoo->get('path/to/index.tpl', $data);

[edit] Using Template and Data objects

In this example we add the Dwoo_Data class that serves as a data container, and the Dwoo_Template_File class that represents a template file in your application.

<?php

// Include the main class, the rest will be automatically loaded
include 'path/to/dwooAutoload.php';

// Create the controller, it is reusable and can render multiple templates
$dwoo = new Dwoo();

// Load a template file, this is reusable if you want to render multiple times the same template with different data
$tpl = new Dwoo_Template_File('path/to/index.tpl');

// Create a data set, this data set can be reused to render multiple templates if it contains enough data to fill them all
$data = new Dwoo_Data();
// Fill it with some data
$data->assign('foo', 'BAR');
$data->assign('bar', 'BAZ');

// Output the result ...
$dwoo->output($tpl, $data);
// ... or get it to use it somewhere else
$dwoo->get($tpl, $data);

[edit] Using a Compiler object

If you want to use custom pre- or post-processors, you need to instantiate a Dwoo_Compiler and add the processors to it.

<?php

include 'path/to/dwooAutoload.php';
$dwoo = new Dwoo();
$tpl = new Dwoo_Template_File('path/to/index.tpl');
$data = array('a'=>5, 'b'=>6);

// Create the compiler instance
$compiler = new Dwoo_Compiler();
// Add a pre-processor that is in one of the plugin directories
$compiler->addPreProcessor('Processor_Name', true);
// .. Or a custom filter you made
$compiler->addPreProcessor('Processor_Function_Name');

// Output the result and provide the compiler to use
$dwoo->output($tpl, $data, $compiler);

[edit] Using Dwoo with loops - Blog example

Let's assume you are looping over multiple articles of a blog that you want to display, here is what you can do to do it as lightly as possible :

You first have to create an "article.tpl" template file, the name doesn't matter really it's up to you, here is what goes in :

<div class="article">
    <h1>{$title}</h1>
    {$content}
    <p class="footer">posted by {$author} on {date_format $date "%d/%m/%Y"}</p>
</div>

You will then use this template to render all the articles.

<?php

include 'path/to/dwooAutoload.php';

$dwoo = new Dwoo();
// Load the "article" template
$tpl = new Dwoo_Template_File('path/to/article.tpl');

// Retrieve your data using whatever means you use
$articles = getMyArticles();

// Loop over them
foreach($articles as $article) {
    // Output each article using their data (assuming it is an
    // associative array containing "title", "content", "author"
    // and "date" keys)
    $dwoo->output($tpl, $article);
}


Contents

  • 1 Using Dwoo with your framework of choice
    • 1.1 Dwoo-compatible Frameworks
    • 1.2 Adapters
    • 1.3 Content Management Systems

[edit] Using Dwoo with your framework of choice

[edit] Dwoo-compatible Frameworks

These frameworks include some support for Dwoo, either as their default view engine or as an optional one :

  • ray (link and public release should come one day.. :) )
  • If you are working on anything let me know

[edit] Adapters

Here is a list of adapters that allow you to use Dwoo in conjunction with some of the popular frameworks out there :

  • Agavi
  • Zend Framework
  • Cake PHP (soon, beta available in the forum)

If the framework you use is not present and you do your own adapter, please post it on the forum or mail it so I can include it in Dwoo's distribution.

[edit] Content Management Systems

These CMS use Dwoo as a template engine or allow their extensions developers to use Dwoo inside them :

  • TYPO3 [1] via the dwoo extension.


[edit] API

If you can't find something here, you might want to look at the auto-generated API docs as the wiki is not yet complete.

  • Dwoo_Compiler

[edit] Misc Tutorials

  • Extending Dwoo - Building a central Template class for your application


Contents

  • 1 Extending Dwoo - Writing Plugins
    • 1.1 Functions / Modifiers
      • 1.1.1 Simple function plugin
      • 1.1.2 Precompiled function plugin
      • 1.1.3 Class function plugin
      • 1.1.4 Precompiled class function plugin
    • 1.2 Block
      • 1.2.1 Simple block plugins
      • 1.2.2 Precompiled block plugins
    • 1.3 Filters and Processors
      • 1.3.1 PreProcessors
      • 1.3.2 PostProcessors
      • 1.3.3 Filters

[edit] Extending Dwoo - Writing Plugins

Dwoo plugins come in different flavours, functions/modifiers, blocks and filters. Most of those can be built using simple functions or more complex classes.

Before we start, you should know about those general plugin featuers :

  • Dwoo automatically loads the plugins that are in it's plugin directory, along with those you manually add through Dwoo_Loader::addDirectory. However, for those plugins to work correctly, they must follow some naming conventions. The function/block plugins must be declared as function Dwoo_Plugin_<name> or class Dwoo_Plugin_<name>, while the filters use function Dwoo_Filter_<name> and class Dwoo_Filter_<name> and processors use Dwoo_Processor_. Plugins added manually must not follow those rules as you provide their exact function callbacks when you add them.
  • The parameter names that you define in your plugin and the default values as well are important, because that will define the parameter names to use in the template when you call that plugin, and it will also allow the compiler to detect when a required argument is missing, so that plugins don't have to handle that logic.
  • The main functions for each plugin, the ones that accept the parameters, can have a rest array parameters, which aggregates all unmapped parameters. It has to be declared as "array $rest" or "array $rest=array()" to work as it should. See the array and math plugins for examples.

[edit] Functions / Modifiers

There are three ways of building function plugins, we will explore those, learning how to make a plugin that returns an uppercased string.

[edit] Simple function plugin

This function will be called when the template is ran, with the required arguments, the only requirement is that the first argument must be of type Dwoo and will always be the Dwoo instance that runs the template.

function Dwoo_Plugin_upper(Dwoo $dwoo, $value)
{
    return strtoupper($value);
}

[edit] Precompiled function plugin

The example above is very simple and just wraps a php function into a plugin. That is a bit silly as it adds the function call overhead plus the plugin file loading time for no benefit at all. Because of that, we are going to make it compilable by appending "_compile" to it's name, and this time the first argument will not be of type Dwoo but will be Dwoo_Compiler.

function Dwoo_Plugin_upper_compile(Dwoo_Compiler $compiler, $value)
{
    return 'strtoupper('.$value.')';
}

As you can see, the function now returns what should be done at the template runtime, instead of actually waiting for the run time to act.

While this is a great feature of Dwoo, it is a bit dangerous to fiddle with, and you should be sure you know what you're doing when working with precompiled plugins. Here are some important things to remember :

  • The arguments are passed as "compiled strings", that is, if the template contains {upper "foo"}, the Dwoo_Plugin_upper_compile function will receive it as "foo", quotes included.
  • You must not enclose the variables you output in double quotes or anything, as they already contain whatever they need to be safely parsed by PHP. Just output where they should go in your code.
  • You can only return one "command", indeed as those functions should be capable to be inside other function calls, you can not return a colon (;) or it will break everything.
  • You can NOT make assumptions as to the value of the parameters you get. For example, {upper $foo} will be received as $this->scope['foo'] (as a string). That means that can't have conditions in your compiled functions, because if($value=="foo") will ALWAYS be false.
  • A little exception to the previous rule is for booleans, you can do if($value=='true') or if($value=='false'), but note that true and false are strings here, not real booleans.

You can look at most of Dwoo function plugins's source code for more examples, more than half of them are precompiled functions. The math plugin for example is a very good example of a complex precompiled plugin, as it parses it's input at compile-time to improve the performance a lot at run-time. Since templates are ran more often than they are compiled, this is overall better.

[edit] Class function plugin

If one of your plugins uses several functions, it might be a good idea to regroup them all inside a class. Dwoo class plugins must follow some rules :

  • The constructor's first parameter must be of type Dwoo, you can extend the Dwoo_Plugin class for convenience so that the constructor already does what it needs to, or you can provide that logic yourself.
  • The method that Dwoo will call at runtime is called "process", that's the method that will receive all the plugin parameters so that is where you must define them.
class Dwoo_Plugin_upper extends Dwoo_Plugin
{
    public function process($value)
    {
        return strtoupper($value);
    }
}

A particularity of class plugins is that only one instance of each class is created for the entire template. That means that instance variables are "template-static", they remain present while the template is run, but they are not static across templates. Static variables are of course shared by all instances, nothing special about that. Anyway if you absolutely need per-plugin-call variables, you will have to reset their value in the process() method.

[edit] Precompiled class function plugin

  • It must implement the Dwoo_ICompilable interface.
  • The method that Dwoo will call must now be static and is called "compile" instead of "process", it will receive all the parameters with the Dwoo_Compiler object calling it being first.
class Dwoo_Plugin_upper extends Dwoo_Plugin implements Dwoo_ICompilable
{
    public static function compile(Dwoo_Compiler $compiler, $value)
    {
        return 'strotoupper('.$value.')';
    }
}

[edit] Block

Block plugins on their end, can only be built with classes. You should extend the Dwoo_Block_Plugin class, but your block plugin must still be named Dwoo_Plugin_<name>, NOT Dwoo_Block_Plugin_<name>.

Some Block facts :

  • They have two static methods, preProcessing and postProcessing, that are called at compile time, the first when the block opening tag is encountered, and the other when it's closed. By default those two functions output block-management code that you should only override if you know what you're doing.
  • The block equivalent to the process() method is called init() and must include all parameters, it is called when the block is opened, followed by end() (no parameters) when the block is closed, and finally process() (no parameters) when the block buffer is required by a parent block.
  • The block contents can be accessed in the process function through the buffer property : $this->buffer

[edit] Simple block plugins

Those are the default block type, that you are most likely to want to use, by default they automatically buffer all their content and then process() is called at the end. That's where you should do your work, anyway here is an example :

class Dwoo_Plugin_upper extends Dwoo_Block_Plugin
{
    // parameters go here if you need any settings
    public function init()
    {
    }

    // this can be ommitted, it's called once when the block ends, don't implement if you don't need it
    public function end()
    {
    }

    // this is called when the block is required to output it's data, it should read $this->buffer, process it and return it
    public function process(){
        return strtoupper($this->buffer);
    }
}

[edit] Precompiled block plugins

More complex to build as they make use of the pre and postProcessing functions, precompiled block plugins allowed complex things like if, elseif, foreach, for and so on to be made as plugins completely separated from the compiler.

Those plugins that are completely handled by the compiler should implement the Dwoo_ICompilable_Block interface, which does nothing but tells the compiler that the plugin should not be loaded at runtime, which enhances performances a bit.

The block compiler functions have the particularity to receive two sets of arguments in $params, one set containing the output-ready php safe values, accessible through Dwoo_Utils::getCompiledParams($params), and the other set that contains the original arguments provided by the template source, which are accessible through Dwoo_Utils::getRealParams($params). This is required in some rare cases, but usually the first method is sufficient.

Here is an example that compiles our now famous upper plugin. However this example is quite limited and I advise you to look at for, foreach and if plugins for more advanced implementations.

class Dwoo_Plugin_upper extends Dwoo_Block_Plugin implements Dwoo_ICompilable_Block
{
    public static function preProcessing(DwooCompiler $compiler, array $params, $prepend, $append, $type)
    {
        return Dwoo_Compiler::PHP_OPEN.$prepend.' ob_start(); '.$append . Dwoo_Compiler::PHP_CLOSE;
    }

    public static function postProcessing(DwooCompiler $compiler, array $params, $prepend, $append, $content)
    {
        // the block is responsible for outputting it's entire content (passed as $content),
        // so you can transform it and then return it, but in this case we don't because
        // we want the content to be uppercased at runtime and not at compile time
        return $content . Dwoo_Compiler::PHP_OPEN.$prepend.' $tmp = ob_end_clean(); echo strtoupper($tmp); '.$append . Dwoo_Compiler::PHP_CLOSE;
    }
}

[edit] Filters and Processors

Filters are added to the Dwoo object and they are called after the template rendering, right before it is cached or output.

Processors are filters for the compiler, they can be "pre" or "post" processor, being called before and after compilation.

  • As previously mentionned, filters use the Dwoo_Filter_ class/function prefix and processors use Dwoo_Processor_.
  • That prefix only has to be used if you want to use the autoload capability. In that case, place your file in one of the plugin directories, and then use addFilter('name', true); where name matches the filename and the name found after Dwoo_Filter_ or Dwoo_Processor_.
  • If you are loading a filter from somewhere else, then you must provide a valid callback to the processor/filter function, for example use addFilter('function_name'); for function based filters or addFilter(array($object, 'method')); for class-based filters.

[edit] PreProcessors

Preprocessors are added to the compiler through $compiler->addPreProcessor(), and are called before template compilation. It allows you to do some processing over the template if you need that in your application. For example Dwoo uses that to help supporting Smarty templates, there is a prefilter that converts some unsupported / legacy smarty features into Dwoo ones, transparently.

Here we will see how to create a simple function-based processor that adds a date automatically at the end of every template. You could use a similar processor to force all your templates to have a specific footer, a Google Analytics tracking code or anything.

function Dwoo_Processor_timestamp(Dwoo_Compiler $compiler, $template)
{
    return $template.'{date_format $dwoo.now "%Y-%m-%d"}';
}

To build it as a class-based processor, you can extend Dwoo_Processor, such as :

class Dwoo_Processor_timestamp extends Dwoo_Processor
{
    public function process($input)
    {
        // you can access the compiler in here through $this->compiler
        return $input.'{date_format $dwoo.now "%Y-%m-%d"}';
    }
}

[edit] PostProcessors

Postprocessors are added to the compiler through $compiler->addPostProcessor(), and are called after template compilation. It allows you to process the template after it has been created, if you want to add something to it or whatever.

They are built exactly as preprocessors so see the examples above.

[edit] Filters

Filters are added to the Dwoo instance through $dwoo->addFilter(), and are called after the template is fully rendered, right before it is cached (if cache is in use). You can use those to do some work on the HTML output. For example Dwoo includes an html_format filter that correctly indents the html of your page so that the sources look nicer and are easier to read. Which can be useful especially while developing the site.

They are built exactly like processors excepted that they receive a Dwoo object as parameter and that they use the Dwoo_Filter_ prefix, for example :

function Dwoo_Filter_timestamp(Dwoo $dwoo, $input)
{
    return $input . date('Y-m-d');
}


Converting from Smarty smoothly using the SmartyAdapter

It is perfectly understandable that some people are relunctant to leave Smarty because they have a big codebase using it. Dwoo is compatible syntax-wise and supports most of Smarty's plugins, but on the PHP end things are indeed quite different. To ease that up Dwoo has an adapter class, that adapter mimics a Smarty object in order for your code to keep working as if you were running on Smarty, while in fact it runs on Dwoo.

The benefit of this is that it allows you to try Dwoo and see if it works with all your code or not in a snap. The drawbacks are that it's not as performant (far from it) as running Dwoo directly, and that it does not support all Dwoo features, because of some architectural changes that were made compared to Smarty.

Anyway, enough talk, if you want to try it here is what you need to change :

<?php

// Comment out the smarty include
// include 'path/to/Smarty.class.php';

// Include the main Dwoo class and the Smarty Adapter class
include 'path/to/Dwoo.php';
include 'Dwoo/Smarty/Adapter.php';

// Replace your Smarty class by Dwoo_Smarty_Adapter, i.e. this :
// $smarty = new Smarty();
// Would become :
$smarty = new Dwoo_Smarty_Adapter();

// If you want to get errors when you use an unsupported feature, enable errors like that
$smarty->show_compat_errors = true;

You are set. You can now try to run your site using Dwoo, it should (if you used that last line) trigger errors when it encounters a missing Smarty feature. If that happens, go read the the smarty support list to figure out what you can do about it.


Contents

  • 1 Smarty Support
    • 1.1 Partially Supported
    • 1.2 Unsupported Plugins
    • 1.3 Unsupported Smarty Class Features
      • 1.3.1 Methods
      • 1.3.2 Properties

Smarty Support

Dwoo supports the Smarty template syntax and extends it to provide some other possibilities. Read the Dwoo syntax and syntax shortcuts pages for more info on that.

Partially Supported

These are supported by Dwoo but in a different way than the original Smarty features, so they might or might not work using the Adapter class depending on what you do with them.

  • {section},{sectionelse}
    • They are automatically converted by the smartyCompat preprocessor but you MUST convert them to {for} and {forelse} tags in your templates if you want to use Dwoo in native mode.
  • {php}
    • It's deprecated (you should just use <?php ?> tags) but is supported by the smartyCompat preprocessor.
  • $smarty->register_object()
    • Some features like whitelisting methods are not available since this is pointless with PHP5, you can just make your methods protected if they are not to be accessed from outside the object
  • {strip}
    • The strip block is supported, but the strip modifier had to be renamed to whitespace instead, the smartyCompat preprocessor converts it but as for section tags, you should convert them if you want to use Dwoo in native mode.

Unsupported Plugins

However, Smarty functions and modifiers are not entirely supported. Some will be in future versions, some won't, here is the list and some details about why they are not supported.

Those won't happen :

  • {include_php}
    • This was already deprecated in Smarty and I won't implement it, it is easy enough to write plugins so that you don't have to include php files within the template, or you can use <?php include 'file.php'; ?> if you really need to.
  • {debug}
    • Use {dump}, it will improve over time to provide similar features.
  • {config_load}
    • I don't see the point and so do most people it seems, so rework your structure, define variables in php and let's get rid of this.

Those might/will be implemented :

  • {insert}

And finally, those will probably be implemented one day, but until then you can take those plugins from the Smarty plugins directory and drop them into the Dwoo plugin directory, they should keep working as before. If you have problems please let me know though.

  • {html_checkboxes}
  • {html_image}
  • {html_options}
  • {html_radios}
  • {html_select_date}
  • {html_select_time}
  • {html_table}
  • {popup}
  • {popup_init}

Unsupported Smarty Class Features

Here is the current compatibility list of the Smarty class properties and methods and what I'm going to do about it in the future.

Methods

Will not be supported :

  • clear_config()
  • get_config_vars()
  • config_load()
    • I don't see the point and so do most people it seems, so rework your structure, define variables in php and let's get rid of this.

Supported by Dwoo but hard to mimic within the SmartyAdapter class so they will probably not be implemented :

  • register_resource()
  • unregister_resource()
  • load_filter()

Should be implemented in one of the next versions :

  • clear_compiled_tpl()
    • a bit useless really, clear your compile dir yourself if you really need to, but the lack of this function shouldn't prevent anything from working

Properties

Those will probably never be implemented, they are either useless or should be done through other means in Dwoo :

  • debugging
  • error_reporting
  • debugging_ctrl
  • request_vars_order
  • request_use_auto_globals
  • cache_handler_func
  • autoload_filters
  • default_template_handler_func
  • config_overwrite
  • config_booleanize
  • config_read_hidden
  • config_fix_newlines
  • config_class
  • use_sub_dirs
    • dwoo uses subdirs if you use forward slashes (/) in your cache or compile IDs automatically
  • default_modifiers

Those are probably going to be implemented, but I can't say when yet :

  • debug_tpl
  • cache_modified_check
  • default_resource_type


Contents

  • 1 Dwoo Template Syntax
    • 1.1 Variables
    • 1.2 Functions
    • 1.3 Modifiers
    • 1.4 Blocks
  • 2 Advanced Syntax
    • 2.1 The @ Operator
    • 2.2 Shortcuts

[edit] Dwoo Template Syntax

[edit] Variables

Those are the simplest thing to handle in Dwoo, you just need to know the variable name and you can output it like that : {$name}. So let's say you have a variable called date, you would output it using {$date}.

To handle arrays, if you have for example a variable called article that contains three items, title, author and content, you can access the sub-items by separating the array name and the sub-item by a dot (.) so that it looks like this for example :

<p>The date is {$date}</p>
<div class="article">
  <h1 class="title">{$article.title}</h1>
  <p class="content">{$article.content}</p>
  <p class="title">Posted by : {$article.author}</p>
</div>

[edit] Functions

The function syntax is quite flexible, functions can either be called just like in php, using {upper("hello")} to call the function upper with the parameter hello. This would print HELLO, as the upper function's purpose is to make strings uppercased. In this case the multiple parameters are split using a comma, i.e. {function("a", "b")} will call function with two parameters, a and b.

Here are some {upper("uppercased words")}
prints :
 Here are some UPPERCASED WORDS

The other way is to call a function using named parameters, the same example as above would then become {upper value="hello"}, in this example we explicitly tell it to use hello as the value.

Here are some {upper value="uppercased words"}
prints :
 Here are some UPPERCASED WORDS

Both ways have pros and cons. The first one is shorter and allows you to forget about parameter names, but the second is more flexible when it comes to complex functions with a lot of parameters, because it not only allows you to forget about their order, but you can also skip parameters and provide only those you really need (i.e. see the blocks example).

[edit] Modifiers

Modifiers are simply functions that can be applied on variables or strings to modify them, this syntax is not mandatory, modifiers like upper can be called using the function syntax without any problem, but the alternative exists if you prefer it. To make hello uppercased using the upper function as a modifier, you must do {"hello"|upper}.

Abcd reversed is {"Abcd"|reverse}
prints:
 Abcd reversed is dcbA

Modifiers parameters are split with ":", and multiple modifiers can be applied on the same variable/string as such :

{"test"|spacify:"-"|reverse|upper} equals {upper(reverse(spacify("test", "-")))}
prints:
 T-S-E-T equals T-S-E-T

This example shows that multiple functions are applied from "inside" the parenthesis (right) to the "outside" (left), while multiple modifiers are applied from left to right.

[edit] Blocks

Blocks are started like functions, using {blockname(parameter1, parameter2)} or the named parameter syntax, and they are closed with {/blockname}. Unclosed blocks are automatically closed when one of their parent is closed, or at the template's end, however it's better to close them yourselves to be sure they are closed when you want them to be and to avoid any conflict to arise.

{textformat wrap=10 indent_first=3}
foo bar baz qux quuux
{/textformat}
prints:
   foo bar
baz qux
quuux

[edit] Advanced Syntax

[edit] The @ Operator

If you use the modifier syntax on an array and prepend the modifier with an @, the modifier will be applied to every element of the array.

For example, the following :

{assign array('ab', 'cd') myArray}
{foreach $myArray|reverse element}
  {$element}
{/foreach}

would output cd ab as the reverse modifier reversed the array elements order before looping over them.

However, if we do :

{assign array('ab', 'cd') myArray}
{foreach $myArray|@reverse element}
  {$element}
{/foreach}

would output ba dc as with the @, reverse was not applied to the array but to 'ab' and then to 'cd', reversing each character sequence.

[edit] Shortcuts

Read more about shortcuts to write templates faster.


Assigns a value to a variable

assign(mixed $value, string $var)
  • value : the value that you want to save
  • var : the variable name (without the leading $)

Example :

{assign 'test string' myVar}
Variable contains: {$myVar}

Output:

Variable contains: test string

Note that this plugin was mostly provided for smarty compatibility, it is easier to do it with the = operator, just as in any language, using :

{$myVar='test string'}


Uppercases the first letter of each word in the given string

capitalize(string $value [, bool $numwords = false ] )
  • value : string to capitalize
  • numwords : whether or not to capitalize words with numbers

Example:

{capitalize('this is a string what2')}

Output:

This Is A String what2


Concatenates any number of variables or strings fed into it

cat(array $rest)
  • rest : two or more strings that will be merged into oneUppercases the first letter of each word in the given string

Example:

{$a='abc'}
{$d='def'}
{$g='ghi'}
{cat $a $d $g}

Output:

abcdefghi


Counts the characters in a string

count_characters(string $value, [ bool $count_spaces = false ])
  • value : the string to process
  • count_spaces : if true, the white-space characters are counted as well

Example:

{count_characters('ab cd')}
{count_characters('ab cd', true)}

Output:

4
5


Counts the paragraphs in a string

count_paragraphs(string $value)
  • value : the string to process

Example:

{count_paragraphs('ab cd')}
{count_paragraphs('ab\n cd')}

Output:

1
2


Counts the sentences in a string

count_sentences(string $value)
  • value : the string to process

Example:

{count_sentences('ab cd')}
{count_sentences('ab. cd')}

Output:

1
2


Counts the words in a string

count_words(string $value)
  • value : the string to process

Example:

{count_words('ab cd')}

Output:

2


Initiates a counter that is incremented every time you call it

counter([ string $name = 'default', [ int $start = 1, [ int $skip = 1, [ string $direction = "up", [ bool $print = true, [ string $assign = null ]]]]]])
  • name : the counter name, define it if you want to have multiple concurrent counters
  • start : the start value, if it's set, it will reset the counter to this value, defaults to 1
  • skip : the value to add to the counter at each call, defaults to 1
  • direction : "up" (default) or "down" to define whether the counter increments or decrements
  • print : if false, the counter will not output the current count, defaults to true
  • assign : if set, the counter is saved into the given variable and does not output anything, overriding the print parameter

Example:

{counter start=10 skip=5}
{counter}
{counter}
{counter start=10 direction=down}
{counter}

Output:

10
15
20
10
5


Cycles between several values and returns one of them on each call

cycle([ string $name = 'default', [ mixed $values = null, [ bool $print = true, [ bool $advance = true, [ string $delimiter = ',', [ string $assign = null, [ bool $reset = false ]]]]]]])
  • name : the cycler name, specify if you need to have multiple concurrent cycles running
  • values : an array of values or a string of values delimited by $delimiter
  • print : if false, the pointer will go to the next one but not print anything
  • advance : if false, the pointer will not advance to the next value
  • delimiter : the delimiter used to split values if they are provided as a string
  • assign : if set, the value is saved in that variable instead of being output
  • reset : if true, the pointer is reset to the first value

Example:

{cycle values=array("1red","2blue","3green")}
{cycle}
{cycle advance=false}
{cycle}
{cycle}
{cycle}
{cycle reset=true}

Output:

1red
2blue
3green
3green
1red
2blue
1red


Formats a date

date_format(string $value, [ string $format = '%b %e, %Y', [ mixed $default = null ]])
  • value : the date, as a unix timestamp, mysql datetime or whatever strtotime() can parse
  • format : output format, see http://php.net/strftime for details
  • default : a default timestamp value, if the first one is empty

Example:

{$.now}
{date_format $.now "%Y-%m-%d"}
{date_format $.now "%D"}
{date_format "1994-3-15 10:24:22"}

Output:

1211992444
2008-05-28
05/28/08
Mar 15, 1994


Returns a variable or a default value if it's empty

default(mixed $value, [ mixed $default = ""])
  • value : the variable to check
  • default : fallback value if the first one is empty

Example:

{$var1="foo"}
{$var2=""}
{default $var1 "bar"}
{default $var2 "bar"}
{default $var3 "bar"}

Output:

foo
bar
bar


Executes whatever follows without output. This is basically a cleaner alternative to doing {assign func("foo") var} or to use {capture} to silence some output.

I can't think of any reason to use it in a template, but since it's there for internal reasons, you might as well use it if required.

Example :

{do "foo"}
{do reverse("bar")}

Output:

*nothing*


Dumps values of the given variable, or the entire data if nothing provided

dump([ $var = '$' ])
  • var : the variable to display, by default it shows the current scope


Applies various escaping schemes on the given string

escape([ $value = "", [ $format = 'html', [ $charset = null ]]])
  • value : the string to process
  • format : escaping format to use, valid formats are : html, htmlall, url, urlpathinfo, quotes, hex, hexentity, javascript and mail
  • charset : character set to use for the conversion (applies to some formats only), defaults to the current Dwoo charset

Example:

{"some <strong>html</strong> tags"|escape}

Output:

some &lt;strong&gt;html&lt;/strong&gt; tags


Evaluates the given string as if it was a template

eval(string $var, [ $assign = null ])
  • var : the string to use as a template
  • assign : if set, the output of the template will be saved in this variable instead of being output

Although this plugin is kind of optimized and will not recompile your string each time, it is still not a good practice to use it. If you want to have templates stored in a database or something you should probably use the Dwoo_Template_String class or make another class that extends it


Extends another template, read more about template inheritance for details and examples.

extends(string $file)
  • file : the template (resource name) to extend


Reads a file

fetch(string $file, [ string $assign = null ])
  • file : path or URI of the file to read (however reading from another website is not recommended for performance reasons)
  • assign : if set, the file will be saved in this variable instead of being output


Include allows you to insert other templates into the current template.

include(string $file [, int $cache_time = null [, string $cache_id = null [, string $compile_id = null [, mixed $data = '_root' [, string $assign = null [, array $rest = array() ]]]]]] )
  • file : the resource name to include
  • cache_time : the template cache length in seconds, defaults to null (= will take the Dwoo object cache length)
  • cache_id : the template cache id
  • compile_id : the template compile id
  • data : this is the data array that will be used as the root data for the included template, by default the current data is sent
  • assign : if set, the included file will be assigned to the given variable and it will not be output
  • rest : any number of values that will override the $data argument

As an example, you may have a common header that you would like to include into all of your pages. This can be accomplished like this :

index.html:

<html>
  <head>
    <title>Some awesome website</title>
  </head>
  <body>

    {include('header.html')}

  </body>
</html>

header.html:

<h1>Some awesome website</h1>
<div id="menu">
{loop $menuItems}<a href="{$url}">{$title}</a>{/loop}
</div>

Output:

<html>
  <head>
    <title>Some awesome website</title>
  </head>
  <body>

    <h1>Some awesome website</h1>
    <div id="menu">
      <a href="index.html">Home</a>
      <a href="products.html">Products</a>
      <a href="contact.html">Contact</a>
    </div>

  </body>
</html>


Indents every line of a text by the given amount of characters

indent(string $value, [ int $by = 4, [ string $char = ' ' ]])
  • value : the string to indent
  • by : how many characters should be inserted before each line
  • char : the character(s) to insert

Example:

baseline
{indent "foo bar baz
qux and then what was it
again? quux quuux and so on I think"}

Output:

baseline
    foo bar baz
    qux and then what was it
    again? quux quuux and so on I think


Checks whether a variable is not null

isset(mixed $var)
  • var : variable to check

Example:

{if isset($foo)}SET{else}not set or null{/if}
{$foo=1}
{if isset($foo)}SET{else}not set or null{/if}
{$bar=null}
{if isset($bar)}SET{else}not set or null{/if}

Output:

not set or null
SET
not set or null
Note that doing :
{if $foo}{$foo}{/if}
..is the same as if you used :
{if isset($foo)}{$foo}{/if}


Converts a given string to lower case.

lower(string $value)
  • value : string to convert

Example:

{lower('ThiS IS a STRING')}

Output:

this is a string


Outputs a mailto link with optional spam-proof (okay probably not) encoding

mailto(string $address, [ string $text = null, [ string $subject = null, [ string $encode = null, [ string $cc = null, [ string $bcc = null, [ string $newsgroups = null, [ string $followupto = null, [ string $extra = null ]]]]]]]])
  • address : target email address
  • text : display text to show for the link, defaults to the address if not provided
  • subject : the email subject
  • encode : one of the available encoding (none, js, jscharcode or hex)
  • cc : address(es) to carbon copy, comma separated
  • bcc : address(es) to blind carbon copy, comma separated
  • newsgroups : newsgroup(s) to post to, comma separated
  • followupto : address(es) to follow up, comma separated
  • extra : additional attributes to add to the <a> tag


Computes a mathematical equation

math(string $equation, [ string $format = "", [ string $assign = "", [ array $rest = array() ]]])

  • equation : the equation to compute, it can include normal variables with $foo or special math variables without the dollar sign
  • format : output format, see sprintf() for details
  • assign : if set, the output is assigned into the given variable name instead of being output
  • rest : all math specific variables that you use must be defined, see the example

Example:

{$c=2}
{math "(a+b)*$c/4" a=3 b=5} {* which translates to: ((3+5)*2/4) *}

Output :

4


Converts line breaks into <br /> tags

nl2br(string $value)
  • value : the string to process


Replaces the search string by the replace string using regular expressions

regex_replace(string $value, string $search, string $replace)
  • value : the string to search into
  • search : the string to search for, must be a complete regular expression including delimiters
  • replace : the string to use as a replacement, must be a complete regular expression including delimiters

Note that if you want to use backreferences, use \$1 instead of $1, \$2 for $2 and so on, otherwise Dwoo will replace the $1 as if it was a variable.

Example:

{regex_replace "abcdABCD" "/([a-z])/" "\$1*"}

Output:

a*b*c*d*ABCD


Replaces the search string by the replace string

replace(string $value, mixed $search, mixed $replace)
  • value : the string to search into
  • search : the string to search for or an array of strings
  • replace : the string to use as a replacement or an array of strings (matching the search array)

Example:

{replace "abc" "b" "B"} or {"abc"|replace:array(a,c):array(A,C)}

Output:

aBc or AbC


Reverses a string or an array

reverse(string $value, [ bool $preserve_keys = false ])
  • value : the string or array to reverse
  • preserve_keys : if value is an array and this is true, then the array keys are left intact

Example:

{loop reverse(array('a', 'b', 'c'))}{$} {/loop}
{"abc"|reverse}

Output:

c b a
cba


Marks the variable as safe and removes the auto-escape function, only useful if you turned auto-escaping on

safe(mixed $var)
  • var : the variable to pass through untouched


Adds spaces (or the given character(s)) between every character of a string

spacify(string $value, [ $space_char = ' ' ])
  • value : the string to process
  • space_char : the character(s) to insert between each character

Example:

{spacify 'abcd'}
{spacify 'abcd' '-'}

Output:

a b c d
a-b-c-d


Formats a string using the sprintf function

string_format(string $value, string $format)
  • value : the string to format
  • format : the format to use, see sprintf() for details


Removes all html tags

strip_tags(string $value, [ bool $addspace = true ])
  • value : the string to process
  • addspace : if true, a space is added in place of every removed tag

Example:

{strip_tags "foo<strong>bold</strong>bar"}
{strip_tags "foo<strong>bold</strong>bar" false}

Output:

foo bold bar
fooboldbar


There is currently no text in this page, you can search for this page title in other pages or edit this page.


Truncates a string at the given length

truncate(string $value, [ int $length = 80, [ string $etc = '...', [ bool $break = false, [ bool $middle = false ]]]])
  • value : text to truncate
  • length : the maximum length for the string
  • etc : the characters that are added to show that the string was cut off
  • break : if true, the string will be cut off at the exact length, instead of cutting at the nearest space
  • middle : if true, the string will contain the beginning and the end, and the extra characters will be removed from the middle

Example:

{truncate "this text is really too long, or let's just pretend it is will you?" 30 middle=true}
{strlen truncate("this text is really too long, or let's just pretend it is will you?" 30 middle=true)} {* here we check its length to verify it's 30 chars alright *}

Output:

this text is r... is will you?
30


Converts a given string to upper case.

upper(string $value)
  • value : string to convert

Example:

{upper('This is a String')}

Output:

THIS IS A STRING


Replaces all white-space characters with the given string

whitespace(string $value, [ string $with = ' '])
  • value : the text to process
  • with : the replacement string, note that any number of consecutive white-space characters will be replaced by a single replacement string

Example:

{"a    b  c        d\ne"|whitespace}

Output:

a b c d e


Wraps a text at the given line length

wordwrap(string $value, [ int $length = 80, [ string $break = "\n", [ bool $cut = false ]]])
  • value : the text to wrap
  • length : maximum line length
  • break : the character(s) to use to break the line
  • cut : if true, the line is cut at the exact length instead of breaking at the nearest space

Example:

{wordwrap "abcdefghijklmnopqrstuvwxyz" 8 cut=true}

Output:

abcdefgh
ijklmnop
qrstuvwx
yz


Overrides the compiler auto-escape setting within the block

auto_escape(mixed $enabled)
  • enabled : if set to "on", "enable", true or 1 then the compiler autoescaping is enabled inside this block. set to "off", "disable", false or 0 to disable it

Example:

{$user="<a href=\"javascript:jsAttack()\">EvilTroll</a>"}
{$user} {* => no escaping, if you didn't filter your data in your php code, this is potentially harmful user input *}

{auto_escape on}
{$user} {* here any injected html is escaped so it's safe *}
{/auto_escape}

Output:

<a href="javascript:jsAttack()">EvilTroll</a> => interpreted as HTML by the browser
&lt;a href="javascript:jsAttack()"&gt;EvilTroll&lt;/a&gt; => interpreted as text by the browser


Defines a block that can be extended by a child template

block(string $name)
  • name : block name, create a new block with that same name in the child template to override it

Read the template inheritance page for more details and examples.


Captures all the output within this block and saves it into {$.capture.default} by default, or {$.capture.name} if you provide another name.

capture([ string $name = 'default', [ string $assign = null, [ bool $cat = false ]]])
  • name : capture name, used to read the value afterwards
  • assign : if set, the value is also saved in the given variable
  • cat : if true, the value is appended to the previous one (if any) instead of overwriting itIf the cat parameter is true, the content will be appended to the existing content

Example :

{capture "foo"}
  Anything in here wont show, it will be saved for later use..
{/capture}
Captured: {$.capture.foo}

Output :

Captured: Anything in here wont show, it will be saved for later use..


The comments plugin allows you to put comments in your template files. These comments are handled by Dwoo, and are not sent as output to the browser, unlike HTML comments.

Comments are delimited by {* and *} tags, and can be on a single line or spread across multiple lines.

{* This is a Dwoo comment *}

{*
 * This is a multi line
 * Dwoo comment!
 *}

{*
  This is also a comment
*}


Generic else block, it supports all builtin optional-display blocks which are if, loop, for, foreach and with.

If any of those block contains an else statement, the content between {else} and {/*blockname*} (you do not need to close the else block) will be shown if the block's condition has no been met

Example :

{foreach $array val}
  $array is not empty so we display it's values : {$val}
{else}
  if this shows, it means that $array is empty or doesn't exist.
{/foreach}


Acts as a php elseif block, allowing you to add one more condition if the previous one(s) didn't match. See the if plugin for syntax details.


Similar to the php for statement

for(string $name, mixed $from, [ int $to = null, [ int $step = 1, [ int $skip = 0 ]]])
  • name : foreach name to access it's iterator variables
  • from : array to iterate from (which will translate to 0) or a number as a start value
  • to : value to stop iterating at (if you set an array in $from, this is automatically set to count($array))
  • step : defines the incrementation of the pointer at each iteration

Note that this plugin supports iterator variables through the name parameter and also supports the else plugin

Example:

{for i 0 5} {$i} {/for}

{for i 0 5 2} {$i} {/for}

{$arr=array("Bob","John","Jim")}
{for i $arr}
  {$i} -> {$arr.$i} {* or $arr[$i] *}
{/for}

Output:

0  1  2  3  4  5
0  2  4
0 -> Bob
1 -> John
2 -> Jim


Similar to the php foreach block, loops over an array

foreach(array $from, [ string $key = null, [ string $item = null, [ string $name = 'default', [ string $implode = null ]]]])
  • from : the array that you want to iterate over
  • key : variable name for the key (or for the item if item is not defined)
  • item : variable name for each item
  • name : foreach name to access it's iterator variables
  • implode : if provided, this will be added between every item

Note that this plugin supports iterator variables through the name parameter and also supports the else plugin

Example : Data is :

array(
  'arr' => array(
    array('id'=>1, 'name'=>'Jim'),
    array('id'=>2, 'name'=>'John'),
    array('id'=>3, 'name'=>'Bob'),
  )
)

{foreach $arr val implode=", "}
  {$val.id} - {$val.name}
{/foreach}

Output :

 1 - Jim,
 2 - John,
 3 - Bob
  • The implode parameter allows you to use a comma or whatever you want to use to separate your items in a much easier way than having to do {if $.foreach.name.last}, {/if} inside the foreach block for example.


This is supported for smarty compatibility but you should just use the generic else block instead.


Conditional block, the syntax is very similar to the php one, allowing () || && and other php operators. Additional Dwoo operators and their equivalent php syntax are as follow :

  • eq → ==
  • neq or ne → !=
  • gte or ge → >=
  • lte or le → <=
  • gt → >
  • lt → <
  • mod → %
  • not → !
  • X is [not] div by Y → (X % Y) == 0
  • X is [not] even [by Y] → (X % 2) == 0 or ((X/Y) % 2) == 0
  • X is [not] odd [by Y] → (X % 2) != 0 or ((X/Y) % 2) != 0

Example :

{if 3 == 5}
  never gonna happen
{elseif 3 == 3}
  if you don't see this, the world is coming to its end
{else}
  this will never happen, unless, as previously mentionned, the world is coming to its end
{/if}

Output (hopefully) :

 if you don't see this, the world is coming to its end


Outputs the entire block contents without parsing them as template code.

literal()

This block MUST be closed explicitly using {/literal}, doing it like {/} or closing it's parent block will not work

Example:

{$var=3}
{literal}
 {$var} {* Comments and the strip plugin are an exception to the literal rule as they still behave as expected even within a literal block *}
{/literal}
{$var}

Output:

{$var}
3


Loops over an array of arrays and allows for really simple / small constructs by moving the scope down to each element automatically. It is basically a combination of foreach and with internally.

loop(array $from [, $name = "default ] )

Note that this plugin supports iterator variables through the name parameter and also supports the else plugin

Example:

{loop $users}
    {$id}-{$name}
{/loop}

Data:

'users' => array( 1 => 'Bob', 2 => 'John' )

Output:

1-Bob
2-John

[edit] Accessing the array key

To access the array key you have to use the {$_key} var within the loop, its name is not user-definable to keep this plugin as simple as possible.

[edit] Extra reads

  • About scope usage
  • Using iterator variables


Removes the white-space at the beginning and end of each line, and also removes all line breaks

strip(string $mode = 'default')
  • mode : the stripping mode defines some rules to prevent harmful behavior on some types of content, currently the only special mode is "js" or "javascript" that ensures javascript line comments do not break the script

Example:

{strip}
   spaces between words in a same line
  - are not removed -
     but
   everything
       else
     is
{/strip}

Output:

spaces between words in a same line- are not removed -buteverythingelseis

If you have a template with inline-Javascript, the {strip} plugin might break your script if it contains line comments.

Take a look at this example:

{strip}
<script type="text/javascript">
    // say hello!
    alert("hello!");
</script>
{/strip}

This will render the output to:

<script type="text/javascript"> // say hello! alert("hello!"); </script>

The script is on a single line now, and since the first line is a comment, everything is treated as a comment. To avoid this, use the "js" parameter inside the {strip} plugin.

{strip js}
<script type="text/javascript">
    // say hello!
    alert("hello!");
</script>
{/strip}
  • This will remove all comments inside the script.
  • Be careful to code properly and end each instruction with a ";", otherwise it might become "foo()bar()" and the browser will most likely treat that as an error. Use JSLint to test your code if you have issues.


Formats a string to the given format, you can wrap lines at a certain length and indent them

textformat([ int $wrap = 80, [ string $wrap_char = "\r\n", [ string $wrap_cut = false, [ int $indent = 0, [ string $indent_char = " ", [ int $indent_first = 0, [ string $style = "", [ string $assign = "" ]]]]]]]])
  • wrap : maximum line length
  • wrap_char : the character(s) to use to break the line
  • wrap_cut : if true, the words that are longer than $wrap are cut instead of overflowing
  • indent : amount of $indent_char to insert before every line
  • indent_char : character(s) to insert before every line
  • indent_first : amount of additional $indent_char to insert before the first line of each paragraphs
  • style : some predefined formatting styles that set up every required variables, can be "email" or "html"
  • assign : if set, the formatted text is assigned to that variable instead of being output

Example:

{textformat 10}here is some text that should wrap{/textformat}

{textformat 10 wrap_cut=true}and this one should cut words that go beyoooooooond 10 chars{/textformat}

Output:

here is
some text
that
should
wrap

and this
one should
cut words
that go
beyooooooo
ond 10
chars


Moves the scope down into an array of values, allowing one to type {$var} instead of {$array.var} within the {with} block

with(array $var)
  • var : the array where to move the scope

Example:

{$arr.foo}
{with $arr} {$foo} / {$arr.foo} {/with}

Data:

'arr' => array( 'foo' => 'bar' )

Output:

bar
bar /

Note : The tricky thing with this plugin is that as the scopes moves to another location, you can not access the global variables anymore.

As you can see with the above example, {$arr.foo} within the {with} block is not valid and returns null. To fix this you can use the _parent and _root keywords. $_root links to the top-level scope, and $_parent goes up by one level. The magic $dwoo variable is not affected by this and is accessible in the same way no matter the current scope.

Example:

{with $arr.sub}
{$foo} / {$_root.arr.sub.foo} / {$_parent.foo}
{$_root.url} / {$_parent._parent.url}
{$dwoo.version}
{/with}

Data:

'arr' => array( 'sub' => array( 'foo' => 'bar' ) )
'url' => 'example.org'

Output:

bar / bar / bar
example.org / example.org
0.3.3


Creates a PHP array with the given input

array(array $rest)
  • rest : any number of values of variables, either with named parameters to build an associative array or without for an auto-indexed array

Associative Array Example:

{assign user array(name="Bob" gender="male")}
{$user.name} is {$user.gender}

Output:

Bob is male

Auto-indexed Array Examples:

{assign users array("Bob" "John")}
First user is : {$users.0}
User list : {foreach $users user}{$user} {/foreach}

Output:

First user is : Bob
User list : Bob John


Smarty compatibility layer for block plugins, this is used internally and you should not call it


Formats any html output (must be valid xml where every tag opened is closed) using a single tab for indenting. <pre> and other whitespace sensitive tags should not be affected.


[edit] Template Inheritance

Inheritance brings the concept of Object Oriented Programming to templates, allowing you to define one (or more) base templates that can be extended by child templates. Extending means that the child can override some of the parent areas, read on as it is easier to understand by looking at an example.

[edit] Usage

Let's say you want a default header and footer in your pages, the more common approach to this (without inheritance) is to put at the top and bottom of every template {include "header.html"} and {include "footer.html"}. However this is not very flexible since you can only modify the area between header and footer, and you have to redefine the entire content area in each template. That could be improved by including more than two files but it would quickly become messy to manage.

What you do with template inheritance is define blocks, which are areas that can be overriden by child templates, so your base template will look like this :

> base.html

<html>
  <head>
    <title>{block "title"}My site name{/block}</title>
    {* css includes, etc. *}
  </head>
  <body>
    <h1>{block "page-title"}Default page title{/block}</h1>
    <div id="content">
      {block "content"}
        Welcome to my amazing homepage
      {/block}
    </div>
  </body>
</html>

So what we have here is a file that defines three blocks, title, page-title and content. Those three can -but don't have to- be overriden in a child template, for example if you have a photo gallery you may want to replace the title, so you can do :

> gallery_base.html

{extends "base.html"}

{block "title"}
Gallery
{/block}

By doing this, all pages extending gallery_base.html will have "Gallery" as their title. Note that we did not redefine the content and page-title blocks since these we wanted to keep their default content from base.html.

The next thing you might want to do is define several gallery pages extending gallery_base.

> gallery_home.html

{extends "gallery_base.html"}

{block "title"}Home - {$dwoo.parent}{/block}

{block "page-title"}Gallery home{/block}

{block "content"}
  {foreach $images img}
    <img src="{$img.url}" alt="{$img.description}" />
  {/foreach}
{/block}

As you see we redefined all the blocks here, however in the title block we used {$dwoo.parent}, which tells Dwoo to insert the default content from the parent template in its place. The content block was overriden to display the images of the gallery, and page-title has also be overriden to display a completely different title.

Now if we render gallery_home.html we will get this :

<html>
  <head>
    <title>Home - Gallery</title>
  </head>
  <body>
    <h1>Gallery home</h1>
    <div id="content">
      <img src="/example.jpg" alt="image" />
      <img src="/example2.jpg" alt="image" />
      <img src="/example3.jpg" alt="image" />
    </div>
  </body>
</html>

[edit] Summary

To sum things up, here is a list of short hints and limitations that apply to template inheritance :

  • You currently can not close a block with the short-hand syntax ({/}), you must explicitly do {/block}
  • The parent should define as much {block "name"}...{/block} parts as possible since it will be as flexible as the amount of blocks it has and this process happens entirely during template compilation so it adds nearly no overhead to the whole process
  • The children templates must start with {extends "parent.html"}
  • The children can not define any content besides what's inside {block} tags they override, anything outside of {block} blocks will be removed
  • You can access the parent block content when overriding it through the {$dwoo.parent}
  • The parent can define multiple blocks with the same name, they will all be overriden at once if the child redefines it, and {$dwoo.parent} will vary according to each overriden block
  • The inheritance tree can be as big as you want (meaning you can extend a file that extends another one that extends another one and so on..), but be aware that all files have to be checked for modifications at runtime so the more inheritance the more overhead you add, but unless performance is really a concern for you it shouldn't matter too much


Variable names are limited to /[a-z0-9_]/i, which means all alpha-numeric characters plus the underscore character, they are case-sensitive.

Also, as an advice, I would recommend that you do not use any variable name starting with an underscore ('_') since should I need to add a magic variable I will be using such $_foo named variables, that way everyone avoids bad surprises.

The following are reserved variables :

  • $dwoo
  • $dwoo.parent
  • $_key


[edit] Iterator Variables

Those variables are special variables that are automatically added to the $dwoo variables when you run an iterator plugin (foreach, loop or for).

[edit] Variables

  • first (bool) : true if the item being processed is the first, false otherwise
  • last (bool) : true if the item being processed is the last one, false otherwise
  • index (int) : the index number (starts from 0 and increases by 1 at each iteration)
  • iteration (int) : the iteration number (starts from 1 and increases by 1 at each iteration)
  • show (bool) : true if the loop will display something, false otherwise
  • total (int) : the total amount of items in the array

[edit] Facts

  • You access them through {$dwoo.<plugin (foreach, loop or for)>.<foreach name>.<var>}
  • If you don't provide the name argument to a plugin, it will use the name "default" by default, which means that for example you can access a foreach var with {$dwoo.foreach.default.first}
  • The $dwoo var can be shortened as $ which means that {$.foreach.default.first} would also work.


[edit] Shortcuts

This page will be completed in further details soon, for now here is a quick list of available shortcuts

FOO is the variable term you want to display in all those examples :

  • {%FOO} = {$dwoo.const.FOO}
  • {$.FOO} = {$dwoo.FOO}, i.e. for a {$.get.user_id} = {$dwoo.get.user_id}
  • {$} = the current scope, at first it means the entire template data, but if you use with or loop to move the scope then this will change
  • {$_} = {$_parent}, this is the parent scope, one level higher than the current scope in the template data. {$_._._} will work as {$_parent._parent._parent}
  • {$__} = {$_root}, this is the top level scope, which is always equal to the entire template data.
  • {/} = closes the last opened block