View previous topic :: View next topic |
Author |
Message |
badchecksum Smarty n00b
Joined: 17 Jul 2013 Posts: 4
|
Posted: Wed Jul 17, 2013 12:08 pm Post subject: included templates inside a foreach cannot access variables |
|
|
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 |
|
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Wed Jul 17, 2013 2:13 pm Post subject: |
|
|
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 |
|
badchecksum Smarty n00b
Joined: 17 Jul 2013 Posts: 4
|
Posted: Wed Jul 17, 2013 2:26 pm Post subject: |
|
|
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 |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Wed Jul 17, 2013 7:28 pm Post subject: |
|
|
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 |
|
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Wed Jul 17, 2013 7:34 pm Post subject: |
|
|
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. |
|
Back to top |
|
badchecksum Smarty n00b
Joined: 17 Jul 2013 Posts: 4
|
Posted: Wed Jul 17, 2013 8:40 pm Post subject: |
|
|
Ah, this is great! 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.
|
|
Back to top |
|
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Wed Jul 17, 2013 9:01 pm Post subject: |
|
|
FYI, no need for the =& (pass by ref) in PHP 5. |
|
Back to top |
|
badchecksum Smarty n00b
Joined: 17 Jul 2013 Posts: 4
|
Posted: Thu Jul 18, 2013 6:53 am Post subject: |
|
|
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 |
|
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Thu Jul 18, 2013 1:45 pm Post subject: |
|
|
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 |
|
Back to top |
|
|