PHPでforeachなどを使う時の注意点。ブロックスコープのお話。

PHPにはブロックスコープがないので、foreachなどループ内でセットした変数でもループを抜けた後、変数に値が入っているよ。というお話です。

知らないと思わぬ罠にハマることもあるかも知れませんので、ご注意を。

  
この記事は2年以上前に書かれたものです。
情報が古い可能性があります。

前提条件

  • PHPバージョンは5.3.6で検証。
  • WordPressでforeachを使用。

例1

PHPコード

$mizore = array( 
    '第一話:霙と雨。',
    '第二話:霙とダム。',
    '最終話:霙、砂漠に帰る。'
);
$val = '';
foreach( $mizore as $m ) {
    $val .= $m;
}
var_dump( $m );     //ループの最後のデータが残っている
var_dump( $val );   //連結データ

実行結果

例2

PHPコード

$mizore = array( 
    '第一話:霙とチワワ。',
    '第二話:チワワの涙。',
    '最終話:霙、砂漠に帰る。'
);
foreach( $mizore as $m ) {
    if( !isset( $val ) ) $val = '';
    else $val .= $m;
}
var_dump( $m );     //ループの最後のデータが残っている
var_dump( $val );   //連結データ

実行結果

新しく同名の変数を使用したい場合、変数を初期化することで値がリセットされます。

初期化例1

unsetを使う

$mizore = array( 
    '第一話:霙と雨。',
    '第二話:霙とダム。',
    '最終話:霙、砂漠に帰る。'
);
$val = '';
foreach( $mizore as $m ) {
    $val .= $m;
}

//変数の割当を解除する
unset( $m );

初期化例2

初期化したい値を変数に代入する

$mizore = array( 
    '第一話:霙とチワワ。',
    '第二話:チワワの涙。',
    '最終話:霙、砂漠に帰る。'
);
$val = '';
foreach( $mizore as $m ) {
    $val .= $m;
}

//空文字で初期化する
$m = ''

こんな書き方はしない

&(アンパサンド)で$mizore値を$mに参照渡しが可能ですが、元の値が書き換わってしまうことがあるので特に理由がない限り止めたほうがいいと思います。

PHPコード

$mizore = array( 
    '第一話:霙と雨。',
    '第二話:霙とダム。',
    '最終話:霙、砂漠に帰る。'
);
$val = '';
//&$m(アンパサンド)とか書かない
foreach( $mizore as &$m ) {
    $val .= $m;
}
//こんなことすると元の値まで変わってしまう・・・
$m = '';

上記の例みたいに、参照渡しする時は$m = '';とかすると$mizoreの中身まで変わるので、それを回避する場合は先にunsetで初期化しなければならなくなりますよっと。
今日そんなコードを見かけたのでこんな記事でした。

追記ですが 関数やクラスにすればいいじゃん という声もあるかも知れませんがそこを説明したいわけではないのであえてこういう説明にしているだけです。
というかPHPのためにわざわざforeachを関数やクラス化するのもそれはそれでめんどくさい
WordPressを扱うデザイナーさんに話してた内容なので、対処はご自身のやり方でどうぞ。

ちなみに array_reduce なんて関数もありますね。

  

共有やブックマークなど

コメントは受け付けていません。