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

assign_by_ref does not work with Smarty3

 
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 -> Smarty 3
View previous topic :: View next topic  
Author Message
eposjk
Smarty Rookie


Joined: 07 Oct 2009
Posts: 13

PostPosted: Wed Oct 07, 2009 9:15 pm    Post subject: assign_by_ref does not work with Smarty3 Reply with quote

For now, $smarty->assign_by_ref is an alias to $smarty->assign.

Example:
Code:
$myarray = array('test' => 1);
$smarty->assign_by_ref('a', $myarray);
$myarray['test'] = 2;

{a[test]} is still 1!
Back to top
View user's profile Send private message
U.Tews
Administrator


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

PostPosted: Wed Oct 07, 2009 9:42 pm    Post subject: Reply with quote

Yes. The _by_ref methods have been introduced in Smarty2 mainly to be able to pass objects to the templates in PHP4. In PHP5 these are passed alway as a reference. Decicission was made to discontinue the _by_ref support in Smarty3 as it is not really needed.

For the time being it is just mapped for sort of backward compatibility to Smarty2.

Why should examples like yours to modify variabless after assignment really make sense?
Back to top
View user's profile Send private message
eposjk
Smarty Rookie


Joined: 07 Oct 2009
Posts: 13

PostPosted: Thu Oct 08, 2009 8:45 am    Post subject: Reply with quote

I wrote my own framework which has a base function which reads and assigns data from one database table. For dialogs which need data from two or more tables I use the base function and change the data afterwards:

Code:
class base {
  protected $formdata;
  ...
  function display_base_logic($table) {
    $this->readfromdb($this->formdata, $table);
    $smarty->assign_by_ref('formdata', $this->formdata);
  }
  ...
}

class mynormaltype extends base {
  ...
  function display_logic {
    $this->display_base_logic('table1');
  }
  ...
}

class myspecialtype extends base {
  ...
  function display_logic {
    $this->display_base_logic('table2');
    ... another database select ...
    $this->formdata['somevar'] = $row[0];
    $this->formdata['othervar'] = $row[1];
  }
  ...
}


Does it hurt having a real assign_by_ref function?

What is the recommended way to deal with this situation:
  • check all 94 occurances of $this->formdata if they need another $smarty->assign and hope that this is the only place where I do things like that?
  • hack my own $smarty->assign_by_ref function?
  • stay with Smarty2 ?
Back to top
View user's profile Send private message
douglassdavis
Smarty Junkie


Joined: 21 Jan 2008
Posts: 541

PostPosted: Thu Oct 08, 2009 10:35 am    Post subject: Reply with quote

I think this can be solved with a slight change in logic. Can you assign the data before right you are ready to display it?

If you want everything to be in $this->formdata, perhaps one way to do it would be:


Code:

class base {
  protected $formdata;
  ...

  function display_base_logic($smarty, $table) {
    $this->readfromdb($this->formdata, $table);
  }

 function do_assigns()
 {
    $this->display_logic();
    $smarty->assign('formdata', $this->formdata);
 }
  ...
  function display_logic() {} // abstract if you want it to be
  ...
}

class mynormaltype extends base {
  ...
  function display_logic {
    $this->display_base_logic('table1');
  }
  ...
}

class myspecialtype extends base {
  ...
  function display_logic {
    $this->display_base_logic('table2');
    ... another database select ...
    $this->formdata['somevar'] = $row[0];
    $this->formdata['othervar'] = $row[1];
  }
  ...
}


When you are ready to do the assigns call $obj->do_assign()

I do something like this, except I use individual vars, not one big array. And I pass the smarty object in to the display logic functions so each function can assign as needed. But, either way should work.
Back to top
View user's profile Send private message
eposjk
Smarty Rookie


Joined: 07 Oct 2009
Posts: 13

PostPosted: Thu Oct 08, 2009 4:21 pm    Post subject: Reply with quote

For me, its not about if it can be done with some central architecture changes in application code - the question is "Can Smarty3 be used as drop-in replacement for Smarty2 with no (or maybe a few local) application code changes?"

I dont want to test, debug and manually repair every feature of my application (~22000 lines of PHP code written by me, and 7500 lines of smarty templates).
It should be enought to ensure that all templates compile with Smarty3 and doing some tests to find minor problems which can be fixed locally without restructuring the application.
Back to top
View user's profile Send private message
Michael White
Smarty Rookie


Joined: 08 Oct 2009
Posts: 20

PostPosted: Thu Oct 08, 2009 5:55 pm    Post subject: Discontinuation of _by_ref ... ? Reply with quote

While the original intent of the _by_ref methods may have been for passing objects through to the PHP 4 templates, some people, like myself, have written a fair amount of code relying on the true reference behavior for all variable types.

It is *very* easy to implement the _by_ref methods in Smarty 3 as I have gone in and done so myself.

The main idea is that you create a new class named Referenced_Smarty_Variable that extends Smarty_Variable. Inside the _by_ref methods you simply create new instances of the Referenced_Smarty_Variable instead of using Smarty_Variable.

Also note that the Referenced_Smarty_Variable class overrides the Smarty_Variable constructor and uses references for obtaining and setting the value of the variable.

I really see no reason to potentially break code that is perfectly legal and legitimate PHP 5 code. Is there some sort of performance concern?

-----------------
@ U.Tews: While it may seem odd to modify a variable after assignment, that is largely the point of using references. In my code, I have a block near the top of the script that defines several variables for content. Ex. ($c1 = ''; )

I then call $smarty->assign_by_ref('c1', $c1);
After that I can assign, append, and modify the contents of $c1 anywhere in a script that may be hundreds of lines long and I don't have to scroll all the way to the bottom to see my variable assignments. I use it mostly for convenience and readability of my code, but it is used quite a bit throughout several applications.
------------------

I can post the code if anyone is interested but it has only been lightly tested as it is essentially just a proof of concept and a hack to support my existing code.
Back to top
View user's profile Send private message Visit poster's website
eposjk
Smarty Rookie


Joined: 07 Oct 2009
Posts: 13

PostPosted: Fri Oct 09, 2009 9:01 am    Post subject: Re: Discontinuation of _by_ref ... ? Reply with quote

Michael White wrote:
I can post the code if anyone is interested but it has only been lightly tested as it is essentially just a proof of concept and a hack to support my existing code.

This would be great!
Back to top
View user's profile Send private message
Michael White
Smarty Rookie


Joined: 08 Oct 2009
Posts: 20

PostPosted: Fri Oct 09, 2009 12:28 pm    Post subject: Smarty 3 Code with support for true assign_by_ref Reply with quote

The code posts below are just small snippets. I've placed the file name and class name (if any) that they belong inside just above each snippet block.

Note: This assign_by_ref() method does not support the new feature in Smarty 3 where you can assign multiple variables at once. I figure that this is ok though since the Smarty team has decided to deprecate this feature and any existing code won't try to assign multiple variables at once.

Also, the "// @mod" and "// @end-mod" comments are just some little tags that I use whenever I have to modify third-party code. It allows me to see exactly what was changed without having to look back into a code repository for it.

File: smarty/libs/sysplugins/internal.templatebase.php
Class: Smarty_Internal_TemplateBase
Task: Replace the current assign_by_ref() method with this one.
Code:

    // @mod
    /**
    * assigns values to template variables by reference
    * wrapper to assign
    */
    public function assign_by_ref($tpl_var, &$value, $nocache = false, $scope = SMARTY_LOCAL_SCOPE)
    {
       #$this->assign($tpl_var, $value, $nocache, $scope);
      if($tpl_var != '') {
         $this->check_tplvar($tpl_var);
         $this->tpl_vars[$tpl_var] = new Referenced_Smarty_variable($value, $nocache, $scope);
      }
    }
   // @end-mod
?>





Note: The reason that the Referenced_Smarty_Variable class needs to extend the Smarty_Variable class is in case they use type hinting in their method declarations or check the type using "instanceof".

File: smarty/libs/sysplugins/internal.templatebase.php
Class: (not applicable)
Task: Insert this class definition just after the Smarty_Variable class.
Code:

// @mod
/**
* class for the Smarty variable object with support for references
*
* This class defines the Smarty variable object for references
*/
class Referenced_Smarty_Variable extends Smarty_Variable {
    // template variable
    public $value;
    public $nocache;
    public $scope;
    /**
    * create Smarty variable object
    *
    * @param mixed $value the value to assign
    * @param boolean $nocache if true any output of this variable will be not cached
    * @param boolean $scope the scope the variable will have  (local,parent or root)
    */
    public function __construct(&$value = null, $nocache = false, $scope = SMARTY_LOCAL_SCOPE)
    {
        $this->value = &$value;
        $this->nocache = $nocache;
        $this->scope = $scope;
    }
}
// @end-mod
[/b]
Back to top
View user's profile Send private message Visit poster's website
mohrt
Administrator


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

PostPosted: Fri Oct 09, 2009 1:27 pm    Post subject: Reply with quote

The assign_by_ref() original intention in Smarty 2 was to work around the object-by-copy behavior of PHP4. Since we have developers out there relying on the assign by reference behavior itself, I don't see a problem making it BC in Smarty 3. You should see it in a future SVN update.
Back to top
View user's profile Send private message Visit poster's website
Michael White
Smarty Rookie


Joined: 08 Oct 2009
Posts: 20

PostPosted: Fri Oct 09, 2009 1:34 pm    Post subject: Reply with quote

Looking forward to it! And thank you!
Back to top
View user's profile Send private message Visit poster's website
eposjk
Smarty Rookie


Joined: 07 Oct 2009
Posts: 13

PostPosted: Fri Oct 09, 2009 3:38 pm    Post subject: Reply with quote

@Michael White: Thanks!

@mohrt: That sounds great!
Back to top
View user's profile Send private message
U.Tews
Administrator


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

PostPosted: Sun Oct 11, 2009 8:26 pm    Post subject: Reply with quote

The by_ref methodes have now been reenabled with the latest SVN update.
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 -> Smarty 3 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