0

I've got a recursive function searching an object by index in a multidimensional, associative array.

$settings = array(
'title' => new XCPreferenceShortText('title'),
'html' => new XCPreferenceLongText('html'),
'_blog' => array(
    '_blog' => new XCPreferenceHeading('blog'),
    'acceptcomments' => new XCPreferenceBoolean('acceptcomments'),
    'per_page' => new XCPreferenceNumberSet('per_page')
),
'_publishing' => array(
    '_publishing' => new XCPreferenceHeading('publishing'),
    'published' => new XCPreferenceBoolean('published'),
    'publishon' => new XCPreferenceDate('publishon'),
)
);

The code traverses the array and whenever is_array($value) returns true, it recurses the whole thing.

function &find($idx, $pref_array = false) {

    if ($pref_array === false)
        $pref_array = &$this->preferences;

    foreach ($pref_array as $key => $data) {
        if (is_array($data)) {
            $res = $this->find($idx, $data);
            if ($res !== false)
                return $res;
        }
        else if ($key == $idx)
            return $pref_array[$idx];
    }

    return false;
}

This function finds (and returns a reference to the result) an object associated to a given key – but when I store the return value / reference in a variable and set that var to null, this has no effect on the actual element in the "original" array.

0

2 Answers 2

1

You have to call the function like this:

$value = &find($idx);
$value = null;
//just to be safe, in case you re-use $value later on
unset($value);

Saying the function returns by reference is insufficient to create a store a reference on calling.

By the way, you should be aware an iterator called RecursiveArrayIterator exists.

Sign up to request clarification or add additional context in comments.

4 Comments

(Sorry to annoy you again) I don't think so... this doesn't clear the array's reference to the object found, only a new reference created when find returns. Or does it?
@Mvan Well, you can test it: codepad.viper-7.com/ISR2lq In place of the object is now a NULL.
@ban Read the question. All the OP wants to do is to replace the value in the array with NULL. He doesn't want to unset the array element. There is actually a caveat to my answer: $value = null; might actually not replace the object with NULL in one very particular situation -- when $value is a proxy object. I don't think that's a very relevant objection in this case, though.
Thanks, I'll need to look into PHP references. And thank you even more for the online PHP interpreter that I couldn't find when I needed it.
0

I improved the function call as Artefacto suggested – but the function still didn't return a reference for elements retrieved by recursion only.

The mistake was, in this case, the recursion call itself. Below you will find an adjusted version which works for me:

foreach ($pref_array as $key => $data) {
        if (is_array($data)) {
            $res = &$this->find($idx, &$pref_array[$key]);
            if ($res !== false)
                return $res;
        }
        else if ($key == $idx) {
            return $pref_array[$idx];
        }
    }

Calling &$this->find($idx, $data); before was wrong as $data actually was no reference. In order to get a reference to the array I just had to fetch the array from the referenced variable ($pref_array).

Thanks a lot guys.

Comments

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.