Smarty Forum Index Smarty
The discussions here are for Smarty, a template engine for the PHP programming language.
included templates inside a foreach cannot access variables

 
Post new topic   Reply to topic    Smarty Forum Index -> General
View previous topic :: View next topic  
Author Message
badchecksum
Smarty n00b


Joined: 17 Jul 2013
Posts: 4

PostPosted: Wed Jul 17, 2013 12:08 pm    Post subject: included templates inside a foreach cannot access variables Reply with quote

I'm currently upgrading an application to v3 from v2, and I've found that a custom include function and plugin that I've been using is no longer working properly.

Here's an example in the template:
Code:

{foreach from=$myitems item=entry}
    {include file="dir/loc/item.tpl"}
    {myblock file="loc/item"}{/myblock}
    {run file="loc/item"}
{/foreach}


The built-in {include} works as I expect: $entry is available in
"dir/loc/item.tpl".

The other two calls are augmented ways of doing the same thing while providing additional functionality. The same template loaded in the latter 2 calls does not have access to $entry in v3, but it does in v2.

How the latter includes work:

I've extended Smarty and added a run() function to the subclass. It also acts as a singleton. The run() function calls $this->display() to load the files after checking to see if an associated PHP script exists. So, in the examples above, it would look for "dir/loc/item.php", and include that, if it exists, prior to displaying the template file "dir/loc/item.tpl" using smarty.

I've looked at the Smarty_Internal_TemplateBase::fetch() code and noticed that it's actually merging sub template vars with parent template vars, so I really don't understand why it's not working the way I expect it to.

Can anyone tell me if what I'm doing should be working in v3, why or why not, and if there's a normal, alternate way of doing this?
Back to top
View user's profile Send private message
mohrt
Administrator


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

PostPosted: Wed Jul 17, 2013 2:13 pm    Post subject: Reply with quote

if $entry has a value inside the foreach loop, I don't see why it wouldn't be there. As a test you could try this:

Code:
{include file="dir/loc/item.tpl" entry=$entry}
Back to top
View user's profile Send private message Visit poster's website
badchecksum
Smarty n00b


Joined: 17 Jul 2013
Posts: 4

PostPosted: Wed Jul 17, 2013 2:26 pm    Post subject: Reply with quote

mohrt

Quote:
The built-in {include} works as I expect: $entry is available in "dir/loc/item.tpl".


The built-in include works fine.
Back to top
View user's profile Send private message
U.Tews
Administrator


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

PostPosted: Wed Jul 17, 2013 7:28 pm    Post subject: Reply with quote

Yes, there is a major difference between Smarty 2 and Smarty 3.

In Smarty 3.1 templates are excuted in the context of the Smarty_Internal_Template class which holds the merged parent and local template variables. This template object is passed as second parameter to your {run...} plugin.
See http://www.smarty.net/docs/en/plugins.functions.tpl

You must call $template->display(...) from your plugin to see also the variables assigned within the calling template.

A singleton of the Smarty object ($this->display(...) ) will always see only the variables originally assgined to the Smarty object.
Back to top
View user's profile Send private message
mohrt
Administrator


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

PostPosted: Wed Jul 17, 2013 7:34 pm    Post subject: Reply with quote

badchecksum wrote:
mohrt

Quote:
The built-in {include} works as I expect: $entry is available in "dir/loc/item.tpl".


The built-in include works fine.


Ah, mis-read that. Smile
Back to top
View user's profile Send private message Visit poster's website
badchecksum
Smarty n00b


Joined: 17 Jul 2013
Posts: 4

PostPosted: Wed Jul 17, 2013 8:40 pm    Post subject: Reply with quote

U.Tews wrote:

See http://www.smarty.net/docs/en/plugins.functions.tpl

You must call $template->display(...) from your plugin to see also the variables assigned within the calling template.


Ah, this is great! Very Happy Thank you so much. Now my run function can do this:

Code:

public function run($params, $template=null)
{
    if (!is_object($template))
        $template =& $this; // $this is smarty
        ...
}


... and the block functions can pass their $smarty parameter as $template, and it works perfectly in all cases again. Thanks again. This saved me so much trouble.

And thanks mohrt for taking a look, too.
Very Happy
Back to top
View user's profile Send private message
mohrt
Administrator


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

PostPosted: Wed Jul 17, 2013 9:01 pm    Post subject: Reply with quote

FYI, no need for the =& (pass by ref) in PHP 5.
Back to top
View user's profile Send private message Visit poster's website
badchecksum
Smarty n00b


Joined: 17 Jul 2013
Posts: 4

PostPosted: Thu Jul 18, 2013 6:53 am    Post subject: Reply with quote

mohrt wrote:
FYI, no need for the =& (pass by ref) in PHP 5.


That's a reference assignment. It's a style choice in the case of what I posted. In general, I prefer to indicate explicitly when I'm using a variable as a reference to another. And references created by a standard assignment versus explicit reference assignment do have different behaviors.

Code:

$obj = new stdClass();
$obj->test = "member";

$ref = $obj;
$ref = "variable"; // only $ref is set to "variable"

$ref =& $obj;
$ref = "variable"; // $ref and $obj are set to "variable"


Re-using variables (as in the first case) can be very helpful, but it can also obfuscate the code if it's used all the time. If I'm creating a variable to use it solely as a reference, I want it to be clear that that's what it is.
Back to top
View user's profile Send private message
mohrt
Administrator


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

PostPosted: Thu Jul 18, 2013 1:45 pm    Post subject: Reply with quote

badchecksum wrote:
mohrt wrote:
FYI, no need for the =& (pass by ref) in PHP 5.


That's a reference assignment. It's a style choice in the case of what I posted. In general, I prefer to indicate explicitly when I'm using a variable as a reference to another. And references created by a standard assignment versus explicit reference assignment do have different behaviors.

Code:

$obj = new stdClass();
$obj->test = "member";

$ref = $obj;
$ref = "variable"; // only $ref is set to "variable"

$ref =& $obj;
$ref = "variable"; // $ref and $obj are set to "variable"


Re-using variables (as in the first case) can be very helpful, but it can also obfuscate the code if it's used all the time. If I'm creating a variable to use it solely as a reference, I want it to be clear that that's what it is.


I see, I didn't see it was intended for handling a reset of the variable, but for referencing the object itself like PHP4 did.

Code:
$obj = MyObj();
$a = $obj;
$b =& $obj;

$a->foo = "zip";
$b->foo = "zap";

echo $a->foo; // zap
echo $b->foo; // zap


reference or not, it is the same object. and yeah, references usually lead to difficult-to-debug code, so I just avoid em unless there is a strong case for it Smile
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Smarty Forum Index -> General 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