Help! Recursive array search - return by reference.

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
josamoto
Forum Commoner
Posts: 41
Joined: Fri Aug 24, 2007 6:57 am
Location: South Africa
Contact:

Help! Recursive array search - return by reference.

Post by josamoto »

Hi all!

We all know how easy it is to return variables by reference. Consider the following code:

Code: Select all

<?php
$array = array('alpha','beta','charley');
 
function &getSomething(&$array) {
    $result =& $array[1];
    return $result;
}
 
$something =& getSomething($array);
$something = 'funky chicken';
 
?>
<pre>
<?php print_r($array);?>
</pre>
The above sample works as expected, the middle element from $array is returned, and modified via $something. The changes reflect in $array because getSomething returned the value by reference.

I'm trying to take the above one step further...a recursive array searh function as follows:

Code: Select all

<?php
/**
 * Contains basic functionality for dealing with arrays.
 */
class ArrayUtil
{
    /**
     * Performs a recursive search on the given associative array $ar. It will return, by reference, they element found as
     * indicated by the given $searchKey and $findValue.
     *
     * @param array $ar The associative array to search through.
     * @param string $searchKey The key value used for matching.
     * @param string $findValue The value for the key to match.
     *
     * @return Returns BY REFERENCE, the array element if found! Thus, you can modify it directly.
     */
    public static function &findRecursive(&$ar, $searchKey, $findValue) {
        $result = null; // Contains the located element, null if none.
 
        // Check parameters
        if(!isset($ar, $searchKey, $findValue) || !is_string($searchKey)  || !is_string($findValue)) {
            throw new Exception('ArrayUtil::findRecursive() call has missing or invalid parameters!');
        }
        if (!is_array($ar)) {
            throw new Exception('ArrayUtil::findRecursive() cannot perform a recursive search. $ar is not an array!');
        }
 
        // Start traversing the given array
        foreach ($ar as $key => $item) {
            // Evaluate, see if this is our "Wanted Bandit"
            if ($key == $searchKey && $item[$searchKey] == $findValue) {
                $result =& $ar;
            }
 
            // Is this an array? Then recurse...go deeper...penetrate...and do not be afraid!!!
            if (is_array($item)) {
                $result =& self::findRecursive($item, $searchKey, $findValue);
            }
 
            // Has our element been found?
            if (isset($result)) {
                return $result;
            }
        }
 
        // Nothing found...sad but true!
        return null;
    }
}
?>
In my code that calls the above function, it returns the array element successfully, but NOT by reference as I expected. Changes do not reflect in the original.
I am suspecting line 37 in the above snippet has a problem.

I call it like this:

Code: Select all

$parent =& ArrayUtil::findRecursive($result, 'id', $value['parent_id']);
and then try to modify it like this:

Code: Select all

if (!isset($parent['children'])) {
    $parent['children'] = array();
}
 
$parent['children'][] = $value;
Can anybody possibly see what I am doing wrong here?

Thanks in advance!!!
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: Help! Recursive array search - return by reference.

Post by requinix »

foreach makes copies of array values. That means $item is a copy.

However $ar[$key] is not. Use that instead.
User avatar
josamoto
Forum Commoner
Posts: 41
Joined: Fri Aug 24, 2007 6:57 am
Location: South Africa
Contact:

Re: Help! Recursive array search - return by reference.

Post by josamoto »

Thanks for the help Tasairis!!!

The problem was on line 29, I changed

Code: Select all

foreach ($ar as $key => $item) {
to

Code: Select all

foreach ($ar as $key => &$item) {
and it works perfectly now! I'm pretty confident your way would work as well, though!

Thanks again!

:)
Post Reply