View previous topic :: View next topic |
Author |
Message |
ilyalyu Smarty Regular
Joined: 03 Nov 2009 Posts: 72
|
Posted: Thu Dec 29, 2011 10:27 am Post subject: Access arguments of the {include} through {$smarty} variable |
|
|
I suggest to add the following syntax to Smarty engine:
parent.tpl: Code: | {include 'child.tpl' var1=1 var2=2 var3=3} |
child.tpl: Code: | {$smarty.include.var1} |
=====
To understand why it can be useful, imagine that var1, var2 and var3 are optional. In this case I could omit these variables:
parent.tpl: Code: | {include 'child.tpl'} |
child.tpl:
The expected output is "" (empty string) because var1 is null. However, this variable may be defined somewhere else:
parent.tpl: Code: | {$var1 = 5} ... {include 'child.tpl'} |
child.tpl:
In this case child.tpl will output "5" instead of the expected "" (empty string). Currently, to avoid this, I must always explicitly define all optional variables even if they should be null:
parent.tpl: Code: | {include 'child.tpl' var1=null var2=null var3=null} |
child.tpl:
If I have many (say 10) optional variables, the above code (that contains varN=null) is quite awkward. |
|
Back to top |
|
rodneyrehm Administrator
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
Posted: Thu Dec 29, 2011 11:00 am Post subject: |
|
|
Code: | {$variable = "foobar"}
{include file="eval:{$variable}"} |
outputs "foobar".
An included template always sees all the variables of the including template. You are free to define additional variables or alter the variable for the included scope by {include
var2=$var1 var1="hello world"}. This has been the behavior since 1812. Changing this, would break backward compatibility.
I'm not sure if this is such a good idea
_________________ Twitter |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Thu Dec 29, 2011 12:04 pm Post subject: |
|
|
Use some unique names for the optional variables which can not conflict with others. It will do the same job..... |
|
Back to top |
|
ilyalyu Smarty Regular
Joined: 03 Nov 2009 Posts: 72
|
Posted: Fri Dec 30, 2011 4:22 am Post subject: |
|
|
rodneyrehm wrote: | An included template always sees all the variables of the including template. ... This has been the behavior since 1812. Changing this, would break backward compatibility. |
I do not suggest to change this behaviour. The standard syntax (i.e. {$var1}) can see all the variables of the including template, but it is possible to use an alternative syntax (i.e. {$smarty.include.var1}) that will see only variables explicitly defined in the last {include} (i.e. it will see {include 'child.tpl' var1=1}, but it will not see {$var1 = 1} {include 'child.tpl'}).
U.Tews wrote: | Use some unique names for the optional variables which can not conflict with others. It will do the same job..... |
This is what I am currently doing, but this is very-very inconvenient. This means that instead of:
{include 'input.html' type='hidden' name='field1' value='default_value'}
I need to use:
{include 'input.html' input_type='hidden' input_name='field1' input_value='default_value'}
and still I have to remember that I should not use $input_type variable (and other variables starting with $input_) anywhere else. This is quite inconvenient. Not to say that this is bad programming technique. |
|
Back to top |
|
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Fri Dec 30, 2011 2:21 pm Post subject: |
|
|
maybe explain the use case for identifying vars this way? the engine is designed on purpose for assigned vars to cascade to child tpls to make things easier, not harder. ie your example with the form inputs, maybe show how this is being used in the template? |
|
Back to top |
|
ilyalyu Smarty Regular
Joined: 03 Nov 2009 Posts: 72
|
Posted: Mon Jan 02, 2012 3:08 pm Post subject: |
|
|
mohrt wrote: | maybe explain the use case for identifying vars this way? |
Imagine that you have smarty template that generates some object (dropdown_menu.tpl that generates dropdown menu, or popup_window.tpl that generates popup window, or wysiwyg_editor.tpl that generates wysiwyg editor). Your template (dropdown_menu.tpl) has optional parameter "width". In some places you use this optional parameter:
{include 'dropdown_menu.tpl' content=... width='100px'}
and in other places you want to OMIT it:
{include 'dropdown_menu.tpl' content=...}
The problem is that you CAN'T omit this optional parameter because you are not sure that the variable $width is not defined somewhere in parent templates. Currently, you have two solutions:
1. You can always specify optional parameter even if you don't need it: {include 'dropdown_menu.tpl' content=... width=null}
2. You can rename optional parameter to make sure that it has unique name: {include 'dropdown_menu.tpl' content=... dropdown_width='100px'}
This may look like not a big problem when you have one optional parameter. However, imagine that you have 10 optional parameters or so:
1. {include 'dropdown_menu.tpl' content=... width=null height=null offset=null color=null background_color=null border_width=null opacity=null timeout=null}
2. {include 'dropdown_menu.tpl' content=... dropdown_width='100px' dropdown_height='200px' dropdown_offset='2px' dropdown_color='red' dropdown_background_color='blue' dropdown_border_width='2px' dropdown_opacity=0.5 dropdown_timeout='300ms'}
In first case we need to explicitly define 10 null parameters. In second case we need to add prefix "dropdown_" 10 times. Now imagine that you have hundreds of such calls in your code.
To solve the above problem you need a way to know that the variable is passed as a parameter of the include and not defined somewhere in parent templates. This is the reason to have alternative syntax with different visibility rule. |
|
Back to top |
|
rodneyrehm Administrator
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
Posted: Mon Jan 02, 2012 3:23 pm Post subject: |
|
|
He's making a valid point.
Why not simply introduce a flag preventing the parent scope being propagated inside the include? Something like {include file="foo" noinherit}?
Uwe, this shouldn't be too much pain? _________________ Twitter |
|
Back to top |
|
ilyalyu Smarty Regular
Joined: 03 Nov 2009 Posts: 72
|
Posted: Mon Jan 02, 2012 6:33 pm Post subject: |
|
|
rodneyrehm wrote: | He's making a valid point. |
I guess I managed to explain what the problem is
rodneyrehm wrote: | Something like {include file="foo" noinherit}? |
I would suggest the solution similar to the one used in php function. By default php function does not see any outside variable, however you can make outside variable visible using "global" keyword:
Code: | function f($local_var)
{
global $global_var;
...
} |
Smarty template on the contrary by default sees outside variables. Why not add a keyword that will make a particular outside variable invisible:
Code: | {include 'template.tpl' local_var=1}
template.tpl:
{local $local_var}
... |
This is more flexible than "noinherit" flag, because you hide only selected variables. Also, you need to add {local $local_var} only once, while "noinherit" flag should be added to each include. |
|
Back to top |
|
rodneyrehm Administrator
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
Posted: Mon Jan 02, 2012 7:01 pm Post subject: |
|
|
ilyalyu wrote: | I would suggest the solution similar to the one used in php function. By default php function does not see any outside variable, however you can make outside variable visible using "global" keyword [
] |
You may be right from a php developer's perspective. But looking at the bigger picture, passing parent values down to includes will stay the default behavior. Skipping all other arguments, the main reason is backward compatibility. Following your advice we'd break each and every smarty template out there. Not a good idea
ilyalyu wrote: | This is more flexible than "noinherit" flag, because you hide only selected variables. Also, you need to add {local $local_var} only once, while "noinherit" flag should be added to each include. |
While you've made a valid point, you're the first one to make it. That infers this not being a very common request. That demands keeping it simple for the masses.
Doing an {include
noinherit} wherever you don't want the parent scope passed down. Doesn't seem to hard to do. Instead of adding a new flag "nonherit", we could also use the existing scope-attribute. {include
scope="none"} or "clean" or something. I guess I'd prefer that over adding yet another flag - if only to prevent confusing when encountering {include
scope="parent" inherit}, which wouldn't be a great thing to do, I presume. _________________ Twitter |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Mon Jan 02, 2012 7:43 pm Post subject: |
|
|
ilyalyu wrote: | {include 'template.tpl' local_var=1}
template.tpl:
{local $local_var}
... |
The above does not work as the variables are made known in the scope of the template before thde template code is executed. So the {local $local_var} tag again does not know the source of it's value.
redneyrehm wrote: | Doing an {include
noinherit} wherever you don't want the parent scope passed down. Doesn't seem to hard to do. Instead of adding a new flag "nonherit", we could also use the existing scope-attribute. {include
scope="none"} or "clean" or something. I guess I'd prefer that over adding yet another flag - if only to prevent confusing when encountering {include
scope="parent" inherit}, which wouldn't be a great thing to do, I presume. |
I'm also not happy with this solution. As it does break with the current rule that subtemplate can see all variables of outer scopes, what about situations where your subtemplate does include further subtemplate which need to access other variables.
Also we are working on Smarty 3.2 where the internals of variable handling will change. This may open up new options and restrictions.
I think we did understand your point. But I would like to stop the discussion how it could be implemented for now and think about how it could be done in 3.2. |
|
Back to top |
|
ilyalyu Smarty Regular
Joined: 03 Nov 2009 Posts: 72
|
Posted: Mon Jan 02, 2012 8:41 pm Post subject: |
|
|
After some thought, my idea is very easily realized with two prefilters:
Code: | Prefilter 1: {include var1=1 var2=2} => {include var1=1 var2=2 local_include_vars=['var1' => 1, 'var2' => 2]}
Prefilter 2: {local $var1} => {$var1 = $local_include_vars.var1} |
But I will wait for Smarty 3.2 and for official solution. Thx. |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Mon Jan 02, 2012 9:28 pm Post subject: |
|
|
ilyalyu wrote: | Prefilter 1: {include var1=1 var2=2} => {include var1=1 var2=2 local_include_vars=['var1' => 1, 'var2' => 2]}
Prefilter 2: {local $var1} => {$var1 = $local_include_vars.var1} |
Prefilter 2 does not make any sense. $var1 does have already the correct value assigned. And Prefilter 1 does not set 'null' values for not mentioned parameters.
But you could run Prefilter 1 and then use {$local_include_vars.var1} instead of {$smarty.include.var1} |
|
Back to top |
|
ilyalyu Smarty Regular
Joined: 03 Nov 2009 Posts: 72
|
Posted: Tue Jan 03, 2012 7:02 am Post subject: |
|
|
It does make sence. Look what will happen if var1 is omited in include:
Code: | Prefilter 1: {include var2=2} => {include var2=2 local_include_vars=['var2' => 2]}
Prefilter 2: {local $var1} => {$var1 = $local_include_vars.var1} |
Now $var1 = null, even if it is defined in parent templates. This is what I expect for local variable. |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Tue Jan 03, 2012 4:53 pm Post subject: |
|
|
ilyalyu wrote: | Now $var1 = null, even if it is defined in parent templates. This is what I expect for local variable. |
Yes, you are right. My major point was that you can omit prefilter 2 and use {$local_include_vars.var1} instead of {$smarty.include.var1} of you initial request. |
|
Back to top |
|
fabdep Smarty n00b
Joined: 06 Jul 2012 Posts: 1
|
Posted: Fri Jul 06, 2012 10:18 am Post subject: |
|
|
ilyalyu wrote: | mohrt wrote: | maybe explain the use case for identifying vars this way? |
Imagine that you have smarty template that generates some object (dropdown_menu.tpl that generates dropdown menu, or popup_window.tpl that generates popup window, or wysiwyg_editor.tpl that generates wysiwyg editor). Your template (dropdown_menu.tpl) has optional parameter "width". In some places you use this optional parameter:
{include 'dropdown_menu.tpl' content=... width='100px'}
and in other places you want to OMIT it:
{include 'dropdown_menu.tpl' content=...}
The problem is that you CAN'T omit this optional parameter because you are not sure that the variable $width is not defined somewhere in parent templates. Currently, you have two solutions:
1. You can always specify optional parameter even if you don't need it: {include 'dropdown_menu.tpl' content=... width=null}
2. You can rename optional parameter to make sure that it has unique name: {include 'dropdown_menu.tpl' content=... dropdown_width='100px'}
This may look like not a big problem when you have one optional parameter. However, imagine that you have 10 optional parameters or so:
1. {include 'dropdown_menu.tpl' content=... width=null height=null offset=null color=null background_color=null border_width=null opacity=null timeout=null}
2. {include 'dropdown_menu.tpl' content=... dropdown_width='100px' dropdown_height='200px' dropdown_offset='2px' dropdown_color='red' dropdown_background_color='blue' dropdown_border_width='2px' dropdown_opacity=0.5 dropdown_timeout='300ms'}
In first case we need to explicitly define 10 null parameters. In second case we need to add prefix "dropdown_" 10 times. Now imagine that you have hundreds of such calls in your code.
To solve the above problem you need a way to know that the variable is passed as a parameter of the include and not defined somewhere in parent templates. This is the reason to have alternative syntax with different visibility rule. |
I got the same problem, this guy is right.
Is there any solution? I will not say to my smarty designer: "hey you must not use that var name or you will screw my template!"
Thanks. |
|
Back to top |
|
|