Home > Enterprise >  Convert string to multidimensional array without eval
Convert string to multidimensional array without eval

Time:02-22

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;
}

CodePudding user response:

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;
}
  •  Tags:  
  • php
  • Related