Search code examples
phparraysarray-mergerecursive-datastructuresarray-unset

advanced unset the value form array PHP


I have two arrays, what consist arrays. I need to merge these arrays recursive. But I need to do this action few times, and

array_merge_recursive()

will apend my data twice, I want to remove element what already exist in target array. $messages array :

array(2) {
   ["messages"]=>
       array(2) {
           ["test.testik"]=>
           string(13) "Це тест"
           ["test2313.tes31231tik"]=>
           string(23) "це тестончик"
       }
   ["validators"]=>
      array(4) {
           ["valid.validik"]=>
           string(36) "Це валідне значення"
           ["joga.jimbo"]=>
           string(27) "Джімбо торбінс"
           ["validka.invalidka"]=>
           string(23) "це інвалідка"
           ["smith.john"]=>
           string(17) "джон сміт"
     }
 }

$allCar array:

array(2) {
      ["messages"]=>
          array(1) {
             ["test2313.tes31231tik"]=>
             string(23) "це тестончик"
            }
      ["validators"]=>
           array(2) {
              ["validka.invalidka"]=>
              string(23) "це інвалідка"
              ["smith.john"]=>
              string(17) "джон сміт"
         }
      }

I wrote some code:

foreach ($messages as $domain => $messagesArray) {
            foreach ($allCat as $d => $mess) {
                if ($domain == $d) {
                    foreach ($messagesArray as $ymlkey => $trans) {
                        foreach ($mess as $ymlk => $transl) {
                            if ($ymlkey == $ymlk) {
                                unset($mess[$ymlk]);
                            }
                        }
                    }
                }
            }
        }

Then when I run recursive merge it append the same values to array. What I am doing wrong ?


Solution

  • This:

            foreach ($allCat as $d => $mess) {
    

    $mess is a temporary COPY of whatever value your foreach() loop is currently working on. When you do your unset($mess...) later on, you're simply unsetting that temporary copy.

    While some might suggest making $mess a reference, this can/will cause problems later on, because $mess will STILL be a reference after the loops end, and reusing the variable later on will now be mucking around with whatever $mess last pointed at in the loop.

    Instead, use the full array/object path reference in the unset call:

    unset($messages[$domain][$d][$ymlkey][$ymkl]) 
    

    or whatever it should be. This way you guarantee you're working with the actual "real" array, and not any of the many temporary copies your nested loops are creating.