d3cima d3cima - 4 months ago 12
PHP Question

PHP references in uasort function

I have

$products = array(
"product1" => [
"a" => ["total" => 1],
"b" => ["total" => 3],
"c" => ["total" => 2],
],
"product2" => [
"d" => ["total" => 3],
"f" => ["total" => 2],
"e" => ["total" => 1],
],
"product3" => [
"g" => ["total" => 3]
],
);


theses are my products and my stocks for each warehouses (warehouse a has 1 item of product1...)

I want to sort each warehouse by stock for each products.
I've done that :

foreach ($products as &$stocks) {
uasort($stocks, function($elmt1, $elmt2) {
return $elmt2["total"] - $elmt1["total"];
});
}


where I print my new array :

array(3) {
["product1"]=>
array(3) {
["b"]=>
array(1) {
["total"]=>
int(3)
}
["c"]=>
array(1) {
["total"]=>
int(2)
}
["a"]=>
array(1) {
["total"]=>
int(1)
}
}
["product2"]=>
array(3) {
["d"]=>
array(1) {
["total"]=>
int(3)
}
["f"]=>
array(1) {
["total"]=>
int(2)
}
["e"]=>
array(1) {
["total"]=>
int(1)
}
}
["product3"]=>
&array(1) {
["g"]=>
array(1) {
["total"]=>
int(3)
}
}
}


It did my job but when I get a closer look I can see the "&" char in only one of the arrays.

Why ?

Answer

Due to the fact that $item - a reference to the last element of the array. You can do this trick:

$array = ['a', 'b', 'c'];
foreach ($array as &$item) {

}
foreach ($array as $item) {
    $item = 1;
}

var_dump($array);

Output:

array(3) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  &int(1)
}

It's not terrible, as long as you do not start to use $item. It is better to make a job with reference in different function

$array = ['a', 'b', 'c'];
$test = function () use (&$array) {
    foreach ($array as &$item) {
    }
};
$test();
var_dump($array);

Output:

array(3) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  string(1) "c"
}

Or try this:

$products = array(
    "product1" => [
        "a" => ["total" => 1],
        "b" => ["total" => 3],
        "c" => ["total" => 2],
    ],
    "product2" => [
        "d" => ["total" => 3],
        "f" => ["total" => 2],
        "e" => ["total" => 1],
    ],
    "product3" => [
        "g" => ["total" => 3]
    ],
);

foreach ($products as $key=>$stocks) {
    uasort($products[$key], function($elmt1, $elmt2) {
        return $elmt2["total"] - $elmt1["total"];
    });
}

var_dump($products);

Output:

array(3) {
  ["product1"]=>
  array(3) {
    ["b"]=>
    array(1) {
      ["total"]=>
      int(3)
    }
    ["c"]=>
    array(1) {
      ["total"]=>
      int(2)
    }
    ["a"]=>
    array(1) {
      ["total"]=>
      int(1)
    }
  }
  ["product2"]=>
  array(3) {
    ["d"]=>
    array(1) {
      ["total"]=>
      int(3)
    }
    ["f"]=>
    array(1) {
      ["total"]=>
      int(2)
    }
    ["e"]=>
    array(1) {
      ["total"]=>
      int(1)
    }
  }
  ["product3"]=>
  array(1) {
    ["g"]=>
    array(1) {
      ["total"]=>
      int(3)
    }
  }
}