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

"to" and "from" Modifiers

 
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 -> Plugins
View previous topic :: View next topic  
Author Message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Tue Aug 31, 2004 9:06 pm    Post subject: "to" and "from" Modifiers Reply with quote

For those who like to use modifiers, here are two that you might find handy.

Every so often I have the need for a modifier that can do assignments. Despite myself, I also sometimes want to make assignments into arrays. The to modifier makes a stab at implementing those features. It should also permit some interesting dynamic accesses to occur a little more simply.

The from modifier is the analogue to the to modifier in that it is used to access a variable. The only reason for this modifier is that it permits more complicated array access.

Notes:
    Unlike normal modifiers, the to modifier does not return a result. You can force it to passthrough the assignment value (to preserve modifier chains) by passing true as the second (optional) parameter.
    The variable being assigned to or retrieved from (as the case may be) is not prefixed by $.
    Only dot-notation is acceptable for arrays.
    Written as an "extension/addon" instead of a pure plugin due to limitations in the way modifier plugins are implemented. Modify to suit your setup.
    This implementation internally uses PHP's eval and var_export, so it isn't going to win any speed awards.
    This implementation needs more testing and has yet to be tested under PHP5.

Example Usage:
Code:
<br/>Assign "bar" to $foo:<br/>
{"bar"|to:"foo"}
$foo = {$foo}<br/>

<br/>Assign $foo to $b.c:<br/>
{$foo|to:"b.c"}
$b.c = {$b.c}<br/>

<br/>Assign "baz" to "a.`$b.c`":<br/>
{"baz"|to:"a.`$b.c`"}
$a.bar = {$a.bar}<br/>

<br/>Assign array $b to $d.a:<br/>
{$b|@to:"d.a"}
$d.a.c = {$d.a.c}<br/>

<br/>Demonstrate Passthrough:<br/>
{"pass on by"|to:lower:true|strtoupper|to:upper}
$lower = {$lower}<br/>
$upper = {$upper}<br/>

<br/>Demonstrate from and to:<br/>
{"foo"|to:"a.bar"}
{"bar"|to:"b.baz"}

<br/>Superfluous retrieval using "b.baz"|from (equivalent to $b.baz):<br/>
{"b.baz"|from}<br/>

<br/>Complicated retrieval assigned to new array element (expect "foo"):<br/>
{"a.`$b.baz`"|from|to:"b.test"}
{$b.test}

Results of Example:
Quote:
Assign "bar" to $foo:
$foo = bar

Assign $foo to $b.c:
$b.c = bar

Assign "baz" to "a.`$b.c`":
$a.bar = baz

Assign array $b to $d.a:
$d.a.c = bar

Demonstrate Passthrough:
$lower = pass on by
$upper = PASS ON BY

Demonstrate from and to:

Superfluous retrieval using "b.baz"|from (equivalent to $b.baz):
bar

Complicated retrieval assigned to new array element (expect "foo"):
foo


Note how {"baz"|to:"a.`$b.c`"} really assigns to $a.bar since the `$b.c` is evaluated by Smarty before being passed to the modifier. Also note that when the value being assigned is an array, you must use the @ qualifier as per usual when passing entire arrays to modifiers.

Sample Implementation:
    I implemented these as methods of a custom class that extends Smarty. This is important as it provides a means for the modifiers to have access to the local instance of Smarty through $this. This may or may not be compatible with PHP5 (untested). In this sample implementation, the custom class is called "LocalSmarty" and the modifiers are manually registered in the constructor.
[php:1:58b10f70a7]<?php
class LocalSmarty extends Smarty {
function LocalSmarty()
{
// [snip]
$this->register_modifier('to', array('LocalSmarty', 'modifier_to'));
$this->register_modifier('from', array('LocalSmarty', 'modifier_from'));
$this->Smarty();
}

function modifier_to($value, $assign, $passthrough=false) {
$arr = '$this->_tpl_vars';
if (strstr($assign, '.')) {
$_assign = explode('.', $assign);
foreach ($_assign as $_path_part){
$arr .= "[".var_export($_path_part, true)."]";
}
} else {
$arr .= "[".var_export($assign, true)."]";
}
$arr .= "=".var_export($value, true).";";
eval($arr);
if ($passthrough) return $value;
}

function modifier_from($var) {
$arr = '$this->_tpl_vars';
if (strstr($var, '.')) {
$_var = explode('.', $var);
foreach ($_var as $_path_part){
$arr .= "[".var_export($_path_part, true)."]";
}
} else {
$arr .= "[".var_export($var, true)."]";
}
eval("\$value=&$arr;");
return $value;
}
}

?>[/php:1:58b10f70a7]
Comments and suggestions are welcome!


Last edited by boots on Wed Sep 01, 2004 7:43 am; edited 4 times in total
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Wed Sep 01, 2004 6:40 am    Post subject: "to" and "from" w/array + object access Reply with quote

Here's a slightly modified version that goes a step further and also uses the dot notation for object member de-refrencing.

Using "from" to retrieve an array item from an object member:
Code:
{'BLOCK.meta.robots'|from} instead of {$BLOCK->meta.robots}


Using "to" to assign a value to an object member:
Code:
{"foo"|to:"BLOCK.title"}

Note this isn't possible with the standard assign function. Since $BLOCK is an object, this is equivalent to $BLOCK->title = "foo". The interesting thing is that the designer need not know whether $BLOCK is an object or array -- the modifier tranparently makes the proper determination of that detail.

I'm posting this one separately since this implementation makes even heaver use of eval and var_export. It works by iteratively checking each item in the given 'key' to determine if it is an object or array. It is an additional performance hit but affords the convenience of always using dot-notation thereby removing any guesses as to when to use "->" or ".". It may turn out to be easier for designers and more flexible for programmers -- behind the scenes you can change from arrays to objects (or vice-versa) without affecting access patterns in the templates. Again, this implementation is not as fast as native access.

This is probably a good time to point out that messju did a really nice compile-time assign function that enables assigning to objects and arrays. It takes a different approach than these modifiers but it sure is quick! If you haven't seen it yet, it is worth checking out.

[php:1:eccf497085]<?php
class LocalSmarty extends Smarty {
function LocalSmarty()
{
// [snip]
$this->register_modifier('to', array('LocalSmarty', 'modifier_to'));
$this->register_modifier('from', array('LocalSmarty', 'modifier_from'));
$this->Smarty();
}

function modifier_to($value, $assign, $passthrough=false) {
$arr = '$this->_tpl_vars';
if (strstr($assign, '.')) {
$_assign = explode('.', $assign);
$i=0;
foreach ($_assign as $_path_part){
$i++;
if ($i==0) {
$arr .= "[".var_export($_path_part, true)."]";
} else {
eval("\$test=&$arr;");
if (is_object($test)) {
$arr .= "->$_path_part";
} else {
$arr .= "[".var_export($_path_part, true)."]";
}
}
}
} else {
$arr .= "[".var_export($assign, true)."]";
}
$arr .= "=".var_export($value, true).";";
eval($arr);
if ($passthrough) return $value;
}

function modifier_from($var) {
$arr = '$this->_tpl_vars';
if (strstr($var, '.')) {
$_var = explode('.', $var);
$i=0;
foreach ($_var as $_path_part){
$i++;
if ($i==0) {
$arr .= "[".var_export($_path_part, true)."]";
} else {
eval("\$test=&$arr;");
if (is_object($test)) {
$arr .= "->$_path_part";
} else {
$arr .= "[".var_export($_path_part, true)."]";
}
}
}
} else {
$arr .= "[".var_export($var, true)."]";
}
eval("\$value=&$arr;");
return $value;
}

}

?>[/php:1:eccf497085]
Back to top
View user's profile Send private message
winoto
Smarty n00b


Joined: 09 Sep 2005
Posts: 2

PostPosted: Mon Sep 12, 2005 9:39 am    Post subject: I cannot use this plugin. How?? Reply with quote

i sparate this plugin into smarty_modifier_to.php and smarty_modifier_from.php. i cannot use <b>to</b> to assign into variable. i get result only with parameter true.

what is problem?? php version??

how can i write user['name']='jhon' (like in php)?? this is very usefull in section in many case. i try with :

{assign var="user.name" value="jhon"}

but {$user.name} give no result.

How should be??
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Mon Sep 12, 2005 2:11 pm    Post subject: Reply with quote

Hi winoto.

Thanks for your interest in these plugins; however, I have the feeling that you didn't read these posts very carefully. You can not implement these plugins as autoloading -- they must be methods on the Smarty object as shown. Furthermore, they do not give transparent syntax nor do they change the behaviour of assign.

If you do want something like that, try these threads instead:

- http://www.phpinsider.com/smarty-forum/viewtopic.php?t=4520
- http://www.phpinsider.com/smarty-forum/viewtopic.php?t=220

Greetings.
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 -> Plugins 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