Q:

PHP variable changes itself although not passed by reference

In the following code, I am having trouble understanding why the variable $service_category_tree changes by itself. Somehow, the subscription_tree alter's the parameter variable although it is not passed by reference.
$service_category_tree = $this->service_category_model->with_request_forms();
foreach ($this->view_data['users'] as &$user) {
    echo md5(serialize($service_category_tree))."<br>"; // To check if the variable is changed.
    $user->service_categories = $this->merchant_model->subscription_tree($user->id, $service_category_tree);
}

The output of the MD5 statement, as you can see shows that the variable is changed:
10066a31bb6e191fbb94b8dc61fd6e55
10066a31bb6e191fbb94b8dc61fd6e55
fd1e22aa74c048e88751c85528d23254
752e0cef4357d7a33e47b90ef207d396
8b5b6ea856080bf32b9bfecc4e43a3f6
8b5b6ea856080bf32b9bfecc4e43a3f6
8b5b6ea856080bf32b9bfecc4e43a3f6
3f3e7619e59e3776c395065e4278c3f8
3f3e7619e59e3776c395065e4278c3f8
dbfebae62d65bd04ce4ce74f2046f90e
34498709256b34ce4d843c1f735c4c6a

The method subscription_tree does not have an ampersand on the second parameter as seen in the following code.
function subscription_tree($merchant_id, $tree_array = NULL){
    if($tree_array === NULL){
        $this->load->model('service_category_model');
        $tree_array = $this->service_category_model->with_request_forms();
    }
    if(is_array($tree_array) && count($tree_array)){
        $my_request_forms = $this->request_forms($merchant_id)->result();
        $my_service_categories = $this->service_categories($merchant_id)->result();
        foreach ($tree_array as &$sc) {

            // Indicate subscribed service categories
            $sc->subscribed = FALSE;
            if(is_array($my_service_categories) && count($my_service_categories)) {
                foreach ($my_service_categories as $my_sc_key => $my_sc) {
                    if($my_sc->id == $sc->id){
                        $sc->subscribed = TRUE;
                        unset($my_service_categories[$my_sc_key]);
                    }
                }
            }

            // Indicate subscribed request forms
            if(is_array($sc->request_forms) && count($sc->request_forms)) {
                foreach ($sc->request_forms as &$rf) {
                    $rf->subscribed = FALSE;
                    if(count($my_request_forms)) {
                        foreach($my_request_forms as $mrf_key => $my_request_form){
                            if ( $my_request_form->id == $rf->id ) {
                                $rf->subscribed = TRUE;
                                unset($my_request_forms[$mrf_key]);
                                break;
                            }
                        }
                    }
                }
            }

        }
    }
    return $tree_array;
}

A:

In PHP objects are always passed by reference:
Thus lines
foreach ($tree_array as &$sc) {

        // Indicate subscribed service categories
        $sc->subscribed = FALSE;

could change the $tree_array object, which is a reference to $service_category_tree
You could also make a deep-copy of your array:
$new_tree = array();

foreach ($service_category_tree as $k => $v) {
    $new_tree[$k] = clone $v;
}

and pass it to the function. Or make a deep-copy in the function...
More info at http://php.net/manual/en/language.oop5.references.php

