0

So I wrote a class that can parse XML documents and create SQL queries from it to update or insert new rows depending on the settings.

Because the script has to work with any amount of nested blocks, the array that I'm putting all the values in has its path dynamically created much like the following example:

$path = array('field1','field2');
$path = "['".implode("']['",$path)."']";

eval("\$array".$path."['value'] = 'test';");

Basically $path contains an array that shows how deep in the array we currently are, if $path contains for instance the values main_table and field I want set $array['main_table']['field']['value'] to 'test'

As you can see I am currently using eval to do this, and this works fine. I am just wondering if there is a way to do this without using eval.

Something like $array{$path}['value'] = 'test'; but then something that actually works.

Any suggestions?

EDIT

The reason I'm looking for an alternative is because I think eval is bad practice.

SECOND EDIT

Changed actual code to dummy code because it was causing a lot of misunderstandings.

15
  • yeah, well. This looks a lot like you are doing it wrong. Can you please show the input XML and the output you want to achieve. You might be able to get this working with Iterators. Commented Apr 28, 2011 at 15:17
  • oh dear god... Variable of variables are wrong, but this is just.. ahhhh <head bursts> (no offense, just joking) Commented Apr 28, 2011 at 15:18
  • This is only a small part of the entire system, and it works perfectly. The reason I do it like this is because you need to be able to set a table, fieldname and multiple other options - per xml block - defining what needs to happen to the data. Nothing is going 'wrong', except me not wanting to use eval. Commented Apr 28, 2011 at 15:19
  • This thing could be usefull :) Commented Apr 28, 2011 at 15:20
  • 3
    A lot of things that work perfectly are wrong nonetheless. A surgeon can operate you with a spoon if he sharpens that, but that doesnt make it any less wrong. So instead of being offended, why not just do as asked and provide the input and desired output. After all, you are the one who asked and wants an alternative to that abomination above, not us ;) Commented Apr 28, 2011 at 15:22

3 Answers 3

4

Use something like this:

/**
 * Sets an element of a multidimensional array from an array containing
 * the keys for each dimension.
 * 
 * @param array &$array The array to manipulate
 * @param array $path An array containing keys for each dimension
 * @param mixed $value The value that is assigned to the element
 */
function set_recursive(&$array, $path, $value)
{
  $key = array_shift($path);
  if (empty($path)) {
    $array[$key] = $value;
  } else {
    if (!isset($array[$key]) || !is_array($array[$key])) {
      $array[$key] = array();
    }
    set_recursive($array[$key], $path, $value);
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

This would definitely work, however I was hoping for a shorthand that would allow me to do this as quick as with eval.
BTW, I'd recommend replacing isset with array_key_exists, since isset will return false, if key is set as null
1

You can bypass the whole counter business with the array append operator:

$some_array[] = 1; // pushes '1' onto the end of the array

As for the whole path business, I'm assuming that's basically an oddball representation of an xpath-like route through your xml document... any reason you can't simply use that string as an array key itself?

$this->BLOCKS['/path/to/the/node/you're/working/on][] = array('name' => $name, 'target' => $target);

3 Comments

I don't think the array append operator works if I want to do two in a row, $some_array[]['name'] = 'test' then $some_array[]['target'] = 'test' will leave me with $some_array[0]['name'] = 'test' and $some_array[1]['target'] = 'target', or can this be bypassed by doing something with current()?
@Kokos: no, it'd create a new one each time. but if you do it like I am, by assign a new array you can append all your elements at the same time.
The = array() is definitely something I will start using, I had been looking previously for a PHP array shorthand much like = ['field'=>'value'] in Actionscript, I never thought of using the normal syntax in cases like this. The "path business" is simply imploding an array with ][, resulting in field][field][field, and then after prefixing [ and suffixing ] I throw this into eval to make an array.
-1

You can use a foreach with variable variables.

// assuming a base called $array, and the path as in your example:
$path = array('field1','field2');

$$path = $array;
foreach ($path as $v) $$path = $$path[$v];
$$path['value'] = 'test';

Short, simple, and much better than eval.

1 Comment

how is this supposed to work, if $$path = $array; implies array to string conversion?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.