smarty icon indicating copy to clipboard operation
smarty copied to clipboard

v4 -> v5: Undefined Variables are Treated Differently

Open j-applese3d opened this issue 4 months ago • 0 comments

I tried upgrading a site to version 5, but ran into some issues that I could not resolve. Specifically, the way Smarty handles variables has changed.

Example:

<?php
// use Smarty\Smarty; // uncomment for v5
require_once 'vendor/autoload.php';

error_reporting(E_ALL);
ini_set('display_errors', '1');

$smarty = new Smarty();
$smarty->display('string:{$TestVarUndefined} is undefined');

Output:

Smarty v4.5.4

Warning: Undefined array key "TestVarUndefined" in [file]_0.string.php on line 18

Warning: Attempt to read property "value" on null in [file]_0.string.php on line 18
is undefined

With a stack trace potentially and more similar warnings.

Smarty v5.4.1

 is undefined

There is no indication that the variable was never assigned.


Why's this a problem?

I would like to know when I make a typo, or forget to assign a variable, but with v5 it'll just become the empty string.

Just use error_unassigned ?

Yes, setting error_unassigned when using v5 will trigger the error, but the problem with this fix is that it will ALSO trigger an error if an undefined variable is used in combination with empty or isset. Like: {if empty($undefinedVar)} Sweet! {else} Oh no! {/if}

PHP's empty and isset work in a special way, suppressing warnings about undefined stuff, and simply returning a boolean.

So, I don't see an easy way to fix this without adding significant complexity to the compiler, so that it treats empty and isset in a special/different way when attempting to access variables/values.

The difference between v4 and v5 is significant in how they work, as v4 compiles to direct array access, whereas v5 uses $_smarty_tpl->getVariable().


The relevant compiled code of the above example is:

// v4
echo $_smarty_tpl->tpl_vars['TestVarUndefined']->value;?>
 is undefined<?php
// v5
echo $_smarty_tpl->getValue('TestVarUndefined');?>
 is undefined<?php

Am I doing something wrong? Following an anti-pattern? Is it unreasonable to expect {if empty($neverAssignedVar)} to work, while also expecting an error if {$neverAssigned} is used?

I apologize If I missed something in the docs!

j-applese3d avatar Oct 18 '24 21:10 j-applese3d