Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /share/CACHEDEV1_DATA/Web/www/libraries/UBBcode/text_parser.class.php on line 228

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /share/CACHEDEV1_DATA/Web/www/libraries/UBBcode/text_parser.class.php on line 228
References in & PHP

Comments Blog About Development Research Sites

References in & PHP

Feb 18, 2008
In my previous post I wrote about types in PHP and mentioned I might also write a bit about references. Coincidentally, today I worked on a problem that required them, so I decided I might as well share it:

Say you have a huge multi-dimensional array, and wish to unset 1 value in it. However, you want to unset it using a function that simply takes 2 arguments: the huge array, and a simple array containing the path to the element. Say for instance you want to unset the element $Array[2][5]['test'][1], the path array would look like this: $path = array(2, 5, 'test', 1);

The problem of course is converting $path into a link to the array element. You can of course traverse the array, but that will only modify a copy of the array. A much more elegant way is to use references, and with that in mind I wrote the following function:
Code (php) (nieuw venster):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 *  Remove (unset) an array element whose path is
 *  given by keyArray
 *  
 *  @param  & $array     A reference to the array to search
 *                       trough.
 *  @param  $pathArray   The path to the element to remove.
 *  @return Either void on succes or false on faillure.      
**/

function removeKey (array & $array, array $pathArray) {  
  while(
sizeOf($pathArray) > 1) {
    $index = array_shift($pathArray);
    if(!isset(
$array[$index]))
      return
false;
    $array  =& $array[$index];
  }
  
  unset($array[current($pathArray)]);
}

First of all, in the function call I used array & $array. In my previous post I already showed how using the array keyword is a form of typehinting, making sure we always get an array there. What the little ampersand does is making sure we get a reference to that array. It is not a copy (as it would normally be), but a little name-sign saying 'Array is located here in my lookup table!'. Effectively, this means that we do not need to return the $array variable to get back a modified version, since any modification directly affects the parameter!

A simple example to illustrate:
Code (php) (nieuw venster):
1
2
3
4
5
6
7
function barify (& $variable) {
  $variable = 'bar';
}


$variable = 'foo';
barify($variable);
echo
$variable; // Echo's "bar";


Now back to our function: the next line is fairly simple: while the sizeOf our path is still bigger than 1, continue. This means once we reach our last entry (the final key so to speak) we stop just before it. Next, we'll chop of the first element of our path (using array_shift()) so our path is a bit shorter and we got the first element, all in one go.

Now, if this index is not actually in our huge array we probably made a mistake (wrong index perhaps?) and the function should break. Returning false is a great way to do this since it gives us an easy way to see if our function failed - much easier than putting try/catch blocks around it and throwing an exception.

However, if the index is present, we reference to that index. This means we now have a reference to some subpart of our array - would you do a print_r of that reference you'd only see a part of the tree! We keep doing this, traversing further and further along the path of our tree till we are at the level above the element we want to unset (remember, since we used while size > 1).

Now we have a reference to the parent level of the element we wish to unset, so we can! Simply using unset($array[$index]) we unset this particular index from the tree, even if it is an array in itself (my first attempt at this algorythm failed in this aspect, as dutch readers can see here). This also means we can unset an entire branch of our tree if we wish!

Smart readers will undubidably now think 'why not use foreach and unset($array) instead of going a level higher and doing unset($array[$index])?'. I thought the same thing, but unsetting a reference directly does, in fact, unset the reference - not the value we were referencing! Why this does work when referencing an array element is anybodies guess - a bit of perculiar behaviour if you ask me, but then again, it does make sense of sorts.

I could go on and on about references, but fact is I couldn't do a better job than the guys at PHP.net - who wrote an extensive article about it here. Several in fact, including some good examples and nifty functions! So if you're eager to learn about them head there, read the works, try some examples and don't fear the painkillers you'll need =]

Note that there is destinct difference between references and pointers (as you know them from C / C++ for example), which you will most likely never have to worry about in your PHP carreer. I know I never do ;)

FragFrog out!

New comment

Your name:
Comment: