2020.04.06
「参照渡し」PHPの配列をforeachを使って値を変更する方法
PHPの配列をforeachを使って表示するケースはよくあると思います。
配列を扱うときにforeachはとても便利ですが、このforeachで値を変数に格納するとき、【値のコピー】が変数に格納されるという仕様があります。
なので、foreachのループの中で値の参照はできますが、値の変更はできません。
そこでforeachのループの中で値を変更したい場合「参照渡し」をしてあげる必要があります。
foreachで配列を回しつつ、配列の値が条件に一致したときに値を変更しようと思ったときにハマりがちな落とし穴について記事にしたいと思います。
目次
PHPの配列をforeachで回して値の変更がうまくいかないケース
まずは値の変更がうまくいかないケースです。
在庫のデータ$dataArrayをforeachでループを回してstockArrayとdataArrayのキー「type」が一致したら、stockArrayのキー「num」に1を足す処理をしてみたいと思います。
サンプルコード
<?php
//在庫のデータを格納
$dataArray = array(
array( 'name' => 'メロン', 'type' => 'fruit' ),
array( 'name' => 'スイカ', 'type' => 'fruit' ),
array( 'name' => 'りんご', 'type' => 'fruit' ),
array( 'name' => 'トマト', 'type' => 'vegetable' ),
array( 'name' => 'トマト', 'type' => 'vegetable' ),
array( 'name' => 'ゴボウ', 'type' => 'vegetable' )
);
//在庫の個数を格納する配列
$stockArray = array(
array( 'name' => '果物', 'type' => 'fruit' , 'num' => 0 ),
array( 'name' => '野菜', 'type' => 'vegetable' , 'num' => 0 ),
array( 'name' => '肉', 'type' => 'meat' , 'num' => 0 )
);
//在庫個数を調べる
foreach ( $dataArray as $data ){
foreach( $stockArray as $key => $value){
if ($data['type'] == $value['type'] ){
$value['num'] = $value['num'] +1;
}
}
};
//在庫情報を表示
foreach( $stockArray as $stock ){
if ( $stock['num'] != 0 ) {
echo $stock['name'] . 'の在庫' . $stock['num'] . '個';
} else {
echo $stock['name'] . 'の在庫なし';
}
if ($stock !== end($stockArray)) {
echo '、';
}
}
?>
この表示結果は下記のようになります。
果物の在庫なし、野菜の在庫なし、肉の在庫なし
在庫数を調べる処理が終わったあとの$stockArrayを「var_dump($stockArray)」で表示するとこのようになり、キー「num」の値変更がうまくいっていないことがわかります。
array(3) { [0]=> array(3) { ["name"]=> string(6) "果物" ["type"]=> string(5) "fruit" ["num"]=> int(0) } [1]=> array(3) { ["name"]=> string(6) "野菜" ["type"]=> string(9) "vegetable" ["num"]=> int(0) } [2]=> array(3) { ["name"]=> string(3) "肉" ["type"]=> string(4) "meat" ["num"]=> int(0) } }
PHPの配列をforeachで回して値の変更を可能にする方法
PHPでは、「&」をつけることで参照渡しができます。
上記のコードの「foreach( $stockArray as $key => $value){」の部分を参照渡しができるように「$value」の前に「&」を追加します。
サンプルコード
<?php
//在庫のデータを格納
$dataArray = array(
array( 'name' => 'メロン', 'type' => 'fruit' ),
array( 'name' => 'スイカ', 'type' => 'fruit' ),
array( 'name' => 'りんご', 'type' => 'fruit' ),
array( 'name' => 'トマト', 'type' => 'vegetable' ),
array( 'name' => 'トマト', 'type' => 'vegetable' ),
array( 'name' => 'ゴボウ', 'type' => 'vegetable' )
);
//在庫の個数を格納する配列
$stockArray = array(
array( 'name' => '果物', 'type' => 'fruit' , 'num' => 0 ),
array( 'name' => '野菜', 'type' => 'vegetable' , 'num' => 0 ),
array( 'name' => '肉', 'type' => 'meat' , 'num' => 0 )
);
//在庫個数を調べる
foreach ( $dataArray as $data ){
foreach( $stockArray as $key => &$value){
if ($data['type'] == $value['type'] ){
$value['num'] = $value['num'] +1;
}
}
unset($value);
};
//在庫情報を表示
foreach( $stockArray as $stock ){
if ( $stock['num'] != 0 ) {
echo $stock['name'] . 'の在庫' . $stock['num'] . '個';
} else {
echo $stock['name'] . 'の在庫なし';
}
if ($stock !== end($stockArray)) {
echo '、';
}
}
?>
表示結果
果物の在庫3個、野菜の在庫3個、肉の在庫なし
うまく表示できました。
「参照渡し」を使わないとforeachで値の変更ができず、ハマることがあるので、備忘録として残しておきたいと思います。