0

I saved template-variables in the DB, e.g.: slider.item1.headline1 = "Headline1". I am using symfony framework. If I just pass "slider.item1.headline1" to the Twig template, that won't be used because the points are interpreted as a multidimensional array (or nested object) (https://symfony.com/doc/current/templates.html#template-variables).

I've now built a routine that converts the string into a multidimensional array. But I don't like the eval(), PHP-Storm doesn't like it either, marks it as an error. How could this be solved in a nicer way (without eval)?

Here my method:

protected function convertTemplateVarsFromDatabase($tplvars): array
{
  $myvar = [];
  foreach ($tplvars as $tv)
  {
    $handle   = preg_replace('/[^a-zA-Z0-9._]/', '_', $tv['handle']);
    $tplsplit = explode('.', $handle);
    
    $mem = "";
    foreach ($tplsplit as $eitem)
    {
      $mem .= "['" . $eitem . "']";
    }
    
    $content = $tv['htmltext'];
    eval('$myvar' . $mem . ' = $content;');
  }
  
  return $myvar;
}
DarkBee
  • 16,592
  • 6
  • 46
  • 58
Beneboy
  • 3
  • 2
  • What is htmltext? Can you provide sample data as it is passed as argument to this function? – trincot Feb 21 '22 at 12:39
  • Does this answer your question? [How to access and manipulate multi-dimensional array by key names / path?](https://stackoverflow.com/questions/27929875/how-to-access-and-manipulate-multi-dimensional-array-by-key-names-path) – CBroe Feb 21 '22 at 12:50

1 Answers1

0

You can indeed avoid eval here. Maintain a variable that follows the existing array structure of $myvar according to the path given, and let it create any missing key while doing so. This is made easier using the & syntax, so to have a reference to a particular place in the nested array:

function convertTemplateVarsFromDatabase($tplvars): array
{
    $myvar = [];
    foreach ($tplvars as $tv)
    {
        $handle   = preg_replace('/[^a-zA-Z0-9._]/', '_', $tv['handle']);
        $tplsplit = explode('.', $handle);

        $current = &$myvar;
        foreach ($tplsplit as $eitem)
        {
            if (!isset($current[$eitem])) $current[$eitem] = [];
            $current = &$current[$eitem];
        }
        
        $current = $tv['htmltext'];
    }
    
    return $myvar;
}
trincot
  • 317,000
  • 35
  • 244
  • 286