2016-01-02 3 views
2

В следующем коде у меня возникли проблемы с пониманием того, почему переменная $service_category_tree сама по себе. Так или иначе, переменная параметра subscription_tree alter, хотя она не передается по ссылке.PHP переменная сама меняет, хотя не передается по ссылке

$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); 
} 

Выход заявления MD5, как вы можете видеть, показывает, что переменная изменяется:

10066a31bb6e191fbb94b8dc61fd6e55 
10066a31bb6e191fbb94b8dc61fd6e55 
fd1e22aa74c048e88751c85528d23254 
752e0cef4357d7a33e47b90ef207d396 
8b5b6ea856080bf32b9bfecc4e43a3f6 
8b5b6ea856080bf32b9bfecc4e43a3f6 
8b5b6ea856080bf32b9bfecc4e43a3f6 
3f3e7619e59e3776c395065e4278c3f8 
3f3e7619e59e3776c395065e4278c3f8 
dbfebae62d65bd04ce4ce74f2046f90e 
34498709256b34ce4d843c1f735c4c6a 

Метод subscription_tree не амперсанд на втором параметре, как показано в следующем коде ,

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; 
} 

ответ

2

В объектах PHP всегда передаются по ссылке:

Таким образом, линии

foreach ($tree_array as &$sc) { 

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

может изменить $tree_array объект, который является ссылкой на $service_category_tree

Вы можете также сделать глубокая копия вашего массива:

$new_tree = array(); 

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

и передать его функции. Или сделайте глубокий-копию в функции ...

Более подробная информация на http://php.net/manual/en/language.oop5.references.php

+0

Я вижу, но переменная $ service_category_tree является массив, а не объект. Однако внутри массива есть объекты. Как мне обойти это? Я не могу напрямую клонировать $ service_category_tree. –

+0

Я сделал это, добавив клонирование объектов и передав их обратно в массив в методе subscription_tree. В принципе: $ curr_sc = clone $ sc; Затем в конце $ tree_array [$ key] = $ curr_sc; –

+0

Массив передается по ссылке. Копия будет создана, если вы попытаетесь изменить элемент напрямую, но в вашем случае это не произойдет, поскольку вы измените ссылочные значения с помощью '& $ sc'. Не меняйте объекты, если они вам не нужны. Или попробуйте 'serialize' /' unserialize' –

Смежные вопросы