2

I am migrating my old PHP 5.2.14 and Smarty 2.6.19 to PHP 7.3.25 + Smarty 3.1.34.

The PHP code base is quite huge and I have used Smarty::_tpl_vars array to access assigned variables.

$smarty->assign("myvar","var-value"); 
$myvar = $smarty->_tpl_vars['myvar']; #this returns "var-value"  

This method seem to have been deprecated and replaced with getTemplateVars

Is there any workaround for having _tpl_vars in the newer version of Smarty

RJ.
  • 332
  • 5
  • 16
  • 1
    What is the problem in using `getTemplateVars()`? – Progman Apr 30 '21 at 19:47
  • As I mentioned, the code base is huge and the migration will take time. During the course of migration, few servers will still run on old php/smarty setup. So I have to make the code work on both versions of PHP till entire servers are upgraded. – RJ. May 01 '21 at 10:17
  • `_tpl_vars` is/was a private field and shouldn't be accessed in the first place. For smarty 2 you have to use `get_template_vars()`, see https://www.smarty.net/docsv2/en/api.get.template.vars.tpl. Depending on the IDE you are using you can use "Replace all" to change the access on `_tpl_vars` to using `get_template_vars()` or even `getTemplateVars()`. Notepad++ also have a "Replace all" which can run over multiple files. Depending on your deploy/upgrade strategy, you might want to use the `SmartyBC` class (https://www.smarty.net/docs/en/bc.tpl). However, you still shouldn't use `_tpl_vars`. – Progman May 01 '21 at 10:35

2 Answers2

2

You could create a polyfill class that wraps the getTemplateVars method by implementing the ArrayAccess interface and assign it to the Smarty instance as _tpl_vars. You would want to test this very carefully in your application. This is a proof of concept that I just whipped out and tested for this answer to demonstrate that it's possible.

In particular you should check to see if the Smarty instance needs to be passed into the constructor by reference in your PHP 5.2 code - I only have 7.4 handy to test with right now.

<?php
class TplVarsPolyfill implements ArrayAccess
{
    private $_smarty;

    public function __construct(Smarty $smarty)
    {
        $this->_smarty  = $smarty;
    }

    public function offsetSet($varName, $value)
    {
        $this->_smarty->assign($varName, $value);
    }

    public function offsetExists($offset)
    {
        $tplVars = $this->_smarty->getTemplateVars();
        return isset($tplVars[$offset]);
    }

    public function offsetUnset($varName)
    {
        $this->_smarty->clearAssign($varName);
    }

    public function offsetGet($offset)
    {
        $tplVars = $this->_smarty->getTemplateVars();
        return isset($tplVars[$offset]) ? $tplVars[$offset] : null;
    }

    /**
     * This is required to convince Smarty to set the instance
     * @see Smarty::__set
     * @return mixed
     */ 
    public function _tpl_vars()
    {
        return $this->_smarty->getTemplateVars();
    }
}

$smarty = new Smarty();
$smarty->_tpl_vars = new TplVarsPolyfill($smarty);

$testVarName = 'foo';
$testVal = 'bar';

$smarty->assign($testVarName, $testVal);

assert($smarty->_tpl_vars[$testVarName]==$testVal, 'Value in polyfill should match what was assigned via assign()');

$polyfillVarName = 'animal';
$polyfillVal = 'wombat';

$smarty->_tpl_vars[$polyfillVarName] = $polyfillVal;

$smartyTemplateVars = $smarty->getTemplateVars();
assert($smartyTemplateVars[$polyfillVarName]==$polyfillVal, 'Value in getTemplateVars() should match what was assigned via polyfill');
Rob Ruchte
  • 3,569
  • 1
  • 16
  • 18
2

Managed a workaround by adding the following snippet in Smarty.class.php of PHP 5.2/Smarty 2

function getTemplateVars($name=null)
{
    return $this->_tpl_vars[$name];
}

I will replace all $smarty->_tpl_vars[] with $smarty->getTemplateVars() and this way ensure backward compatibility.

RJ.
  • 332
  • 5
  • 16