1

I have an XML document called library.xml and I use the PHP function simplexml_load_file() to get a XML object that I can work with. I have a function called traverseObject() which goes through the document and prints out a nested list based on the document.

One of the tags that gets printed out in this nested list is the id tag. I'm trying to collect all the id tags into one array variable called $ids so that I can use them to generate another section of the page. The problem is that when I try to add these ids to the array, it is empty. I've tried just adding the number 5 to the array repeatedly, but it still doesn't work.

Here is what the simplified (for debugging) program looks like:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<div>Test</div>

<?php

$library = simplexml_load_file('095209376/library.xml');

$ids = array();

function traverseObject($object, $map) 
{
    echo "<ul>";
    foreach ($object as $key => $value ){
        if($key == "title"){
            echo "<li><b>" . $object->title . "</b></li>";          
        } else if ($key == "topic"){
            // traverse child elements, if any
            traverseObject($value, $map);
        } else if($key == "id"){
            echo "<i>id: " . $value . "</i>"; 
            $map[] = 5;                         ** <-------- this is the relevant part
        } else { // skip the rest for now
        }
    }
    echo "</ul>";
}

traverseObject($library, $ids);

if($ids == null){

    echo "uh oh";

} else {

    echo "whaaa";
    foreach ( $ids as $key => $value ){

        echo "key: " . $key . ", value: " . $value;

    }

}

?>
</body>

</html>

It should just add a bunch of 5's to the array $ids and then print them out, but as you can see the array `$ids$ is null. Here's what gets printed:

enter image description here

I've looked over the code a bunch of times now, but I can't see anything wrong with it.

2 Answers 2

4

You need to use references in the function declaration; otherwise $map will be treated as a function local variable.

function traverseObject($object, &$map) 
                                 ^
Sign up to request clarification or add additional context in comments.

1 Comment

Wow, I didn't know how little PHP I knew until now. Thanks, Jack.
1

As @Jack said, your problem here is that you are not passing the array by reference. But the reason is not correct. Unlike objects, PHP actually transfers scalar variables (arrays, strings, integers, floats, etc.) by making a copy of the variable whenever you are passing one in a function, or in a loop. This means that both of the following snippets will not modify the value.

function traverseObject($object, $map) {
    // ...
}

foreach ($map as $key => $value) {
    // ...
}

will actually make a new copy of the value, which is different from the one you are manipulating at the top. Thus, you need to pass the value as a reference.

function traverseObject($object, &$map) {
    // ...
}

foreach ($map as $key => &$value) {
    // ...
}

In the case of the function argument, a simple solution could be to manipulate an object instead of an array, as objects are always transferred by reference, and not by copy.

See Official documentation

3 Comments

From the documentation, it seems that you only need to use the reference operator in function declarations. To quote, "No other expressions should be passed by reference, as the result is undefined. For example, the following examples of passing by reference are invalid:" Are we talking about the same thing?
I should add that my code works (or at least seems to work) currently, with the foreach loop as it is. Are you just saying that $key => $value$ is equivalent to $key, &$value$?
For $key, &$value, it's simply a mistake (I've just corrected the snippet). I've simply done too much JavaScript! ;) In any case, the example for the foreach loop is not relevant in your case, as you are not trying to change the value of $value. Anyway, using &$map instead of $map in the method argument should fix your problem.

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.