Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

Access arguments of the {include} through {$smarty} variable

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Feature Requests
View previous topic :: View next topic  
Author Message
ilyalyu
Smarty Regular


Joined: 03 Nov 2009
Posts: 72

PostPosted: Thu Dec 29, 2011 10:27 am    Post subject: Access arguments of the {include} through {$smarty} variable Reply with quote

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:
Code:
{$var1}


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:
Code:
{$var1}


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:
Code:
{$var1}


If I have many (say 10) optional variables, the above code (that contains varN=null) is quite awkward.
Back to top
View user's profile Send private message
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Thu Dec 29, 2011 11:00 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Thu Dec 29, 2011 12:04 pm    Post subject: Reply with quote

Use some unique names for the optional variables which can not conflict with others. It will do the same job.....
Back to top
View user's profile Send private message
ilyalyu
Smarty Regular


Joined: 03 Nov 2009
Posts: 72

PostPosted: Fri Dec 30, 2011 4:22 am    Post subject: Reply with quote

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
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Fri Dec 30, 2011 2:21 pm    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
ilyalyu
Smarty Regular


Joined: 03 Nov 2009
Posts: 72

PostPosted: Mon Jan 02, 2012 3:08 pm    Post subject: Reply with quote

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
View user's profile Send private message
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Mon Jan 02, 2012 3:23 pm    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
ilyalyu
Smarty Regular


Joined: 03 Nov 2009
Posts: 72

PostPosted: Mon Jan 02, 2012 6:33 pm    Post subject: Reply with quote

rodneyrehm wrote:
He's making a valid point.


I guess I managed to explain what the problem is Smile

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
View user's profile Send private message
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Mon Jan 02, 2012 7:01 pm    Post subject: Reply with quote

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 Wink

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
View user's profile Send private message Visit poster's website
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Mon Jan 02, 2012 7:43 pm    Post subject: Reply with quote

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
View user's profile Send private message
ilyalyu
Smarty Regular


Joined: 03 Nov 2009
Posts: 72

PostPosted: Mon Jan 02, 2012 8:41 pm    Post subject: Reply with quote

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
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Mon Jan 02, 2012 9:28 pm    Post subject: Reply with quote

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
View user's profile Send private message
ilyalyu
Smarty Regular


Joined: 03 Nov 2009
Posts: 72

PostPosted: Tue Jan 03, 2012 7:02 am    Post subject: Reply with quote

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
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Tue Jan 03, 2012 4:53 pm    Post subject: Reply with quote

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
View user's profile Send private message
fabdep
Smarty n00b


Joined: 06 Jul 2012
Posts: 1

PostPosted: Fri Jul 06, 2012 10:18 am    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Feature Requests All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP