Hi all,

This mail describes a problem we currently have with ezcTemplate and it 
provides some solutions. Feedback is highly appreciated.


Problem
-------
In a system with lots of nested templates or template overrides the amount of
variables that need to be forwarded to each template may grow out of
proportion. The following example uses three templates: p, q, and r that
forward all variables via includes to the underlying template:


Template p:
{use $a, $b, $c, $d, $e, $f}
{include "q" send $a, $b, $c, $d, $e, $f}


Template q:
{use $a, $b, $c, $d, $e, $f}
Show a: {$a}
{include "r" send $b, $c, $d, $e, $f}


Template r:
{use $b, $c, $d, $e, $f}
Show all variables: {$b}, {$c}, {$d}, {$e}, {$f}


The user application sends all external variables:
$t = new ezcTemplate();
$t->send->a = 1, 
$t->send->b = 2,
...
$t->send->f = 6,
$t->process("p");


In this example, we nested the templates three deep. In real applications (eZ
publish scale) this nesting will be deeper. Another technique some
applications use are template overrides. Basically, a template override
decides dynamically what template to include and execute. An {if} block will
be used in this document to simulate an in general much more complex override 
system:

{use $load_p, $a, $b, $c, $d, $e, $f}
{if $load_p}
    {include "p" send $a, $b, $c}
{else}
    {include "q" send $d, $e, $f}
{/if}


The use-variables: a, b, c, d, e, and f are never used inside the template,
but only forwarded. 


Solution 1: ezcTemplateConfiguration option
-------------------------------------------

An option in the ezcTemplateConfiguration changes the behavior of the
{include} statements. The {include} statement will then forward all the
variables that it got from the user application by default. The modified
example will be:


Template p:
{include "q"}


Template q:
{use $a}
Show a: {$a}
{include "r"}


Template r:
{use $b, $c, $d, $e, $f}
Show all variables: {$b}, {$c}, {$d}, {$e}, {$f}


The user application remains the same:
$t = new ezcTemplate();
$t->send->a = 1, 
$t->send->b = 2,
...
$t->send->f = 6,
$t->process("p");


The {use} block specifies which variables are used directly in that template.
Where the variables come from is not important.


Solution 2: Add a keyword to include
------------------------------------

Same as solution 1, but instead of adding a configuration a special keyword is
added to the include. This triggers the new behavior. For example:

{include "q" with_externals}

or:

{var $local_var = 2}
{include "q" with_externals send $local_var}


Solution 3: Add a block simular to include
------------------------------------------

Same as solution 1, but then add a new block to ezcTemplate that works simular
to include. For example:

{extern "q"}


Solution 4: Globals
-------------------
Variables used in the template, coming directly the user application are 
specified
via the {global} keyword. For example:  


Template p:
{var $local_var = 2}
{include "q" send $local_var}


Template q:
{global $a}
{use $local_var}
Show a: {$a}
{include "r" send $local_var}


Template r:
{global $b, $c, $d, $e, $f}
{use $local_var}
Show all variables: {$b}, {$c}, {$d}, {$e}, {$f}


The user application remains the same:
$t = new ezcTemplate();
$t->send->a = 1, 
$t->send->b = 2,
...
$t->send->f = 6,
$t->process("p");


It is more verbose where a variable comes from. It may be more difficult to
write the template, because the origin of the variable may not always be 
known.

Solution 5: Add external keyword to {use}
-----------------------------------------

Template p:
{var $local_var = 2}
{include "q" send $local_var}


Template q:
{use $local_var, external $a}
Show a: {$a}
{include "r" send $local_var}


Template r:
{use $local_var, external $b, external $c, external $d, external $e, external 
$f}
Show all variables: {$b}, {$c}, {$d}, {$e}, {$f}


The user application remains the same:
$t = new ezcTemplate();
$t->send->a = 1, 
$t->send->b = 2,
...
$t->send->f = 6,
$t->process("p");



Evaluation
----------

Solution 1, 2, and 3 mark in the 'calling template' which variables are
forwarded. Solution 4 and 5 specify in the 'called template' where the
variables come from. 

Advantages and disadvantages for solutions 1, 2, and 3:

+ Easy to write a (single) template. No knowledge is needed where variables
  are made available. {use} specifies only which variables are used inside the
  template.

+ Easy to change in the template code.

- Once a template is written, it may be difficult to 'backtrack' a variable to
  it's declaration. Keep in mind that when 'template overrides' are used, this
  task is difficult without extra runtime information.


Advantages and disadvantages for solutions 4 and 5:

+ Easy to see if a variable comes from the user application or from the
  calling template. 

- Makes templates less generic. Multi-purpose templates may be called from
  anywhere. 

- May be harder to write the template when it's unknown where previous
  templates declare their variables.

- It is not possible to specify a variable that comes from the user
  application unless it's (modified and) sent by the previous template.
  (Making this work would undo the 'easy backtracking' advantage.)


If there are no other solutions I prefer solution 2 or 3. 
-- 
Components mailing list
[email protected]
http://lists.ez.no/mailman/listinfo/components

Reply via email to