PHPでの参照渡しは使わない方がいいとかよく言われていて、実際使う場面も少ないです。
ただそれでも参照渡しを使った方が便利な場面があるのも事実です。
ということで参照渡しはこんなことに使えるよ、という実例をいくつか紹介していきます。
参照とはそもそも何か
PHPでは変数に別名を付けることができます。
それが参照と呼ばれているものです。
参照の作り方は簡単で参照にしたい変数に参照元の変数を =& で代入するだけ
1 2 3 4 5 |
/** 参照元の変数 */ $org = 100; /** $orgの参照を作る */ $ref =& $org; |
この場合でいえば $ref が $org という変数の参照になります。
参照なのでこの2つは全く同じ変数として扱うことが可能です。
つまり運命共同体なので一方の値が変わればそれに応じてもう一方の値も変化するという訳です。
このことは次のPHPでの変数宣言まとめでも書きました。
そしてこの記事でも少し触れているように参照を他の場所に渡すことを参照渡しと呼んでいます。
参照渡しってどんなところで使うの?
じゃあこの参照渡しが何に使われるかというと主に次のような場面
- 関数に値を変更したい変数を参照渡しするため
- foreachのループ内で配列を変更するため
他にも利用例はあるかもですが、思いつくのはこれくらいですね。
それではこの2つについてコード例と一緒に説明していきます。
関数に参照渡しする場合
参照渡しで一番ポピュラーな使い方が関数と一緒に使う方法です。
関数に変数を参照として渡すことでその関数内で変数を変更可能になります。
ではどうやって渡すかというと次のコードのように関数引数に & をつけるだけ
1 |
function my_func( &$arg ){ ... } |
上の例では &$arg というのが $arg という変数の参照になります。
では具体的なコードで関数の参照渡しを考えてみましょう。
例えば渡された配列の各要素を2倍にする関数を作りたいとします。
この処理をするために参照渡しを使っているのが次のコード
1 2 3 4 5 6 7 8 9 10 |
function my_double_arr( &$arr ){ $len = count($arr); for( $i = 0; $i < $len; $i++){ $arr[$i] *= 2; } } $arr = [1, 2, 3]; my_double_arr($arr); print_r($arr); |
関数からは配列を返す必要はありません。
なぜなら参照渡しで渡された変数は関数の外に出ても変更が保存されるからです。
なので print_r($arr); してみると次のように要素が2倍されているのが確認できます。
1 2 3 4 5 6 |
Array ( [0] => 2 [1] => 4 [2] => 6 ) |
こういう風に関数内で引数の変数をそのまま変更できるのが参照渡しの特徴です。
上の例だと参照渡ししなくてもそのまま返り値を返せばいいだけなのであまり意味はないかもしれません。
ですが、次の例のように複数の変数に値をセットしたいときに参照渡しが役に立ちます。
1 2 3 4 |
function my_func( &$a, &$b ){ $a = $a + $b; $b = $a * $b; } |
まあこういう風に複数の参照を取るってことは実際はほとんどないですが・・・
ただそれでも複雑な処理をしたいときにこの方法を知っておけば役に立つかもしれません。
foreachループで参照渡し
次に参照渡しが使えそうなのはforeachループで配列の値を取り出すときです。
もし配列の要素の値を書き換えたいなら参照渡しが役に立ちます。
例えばforeachに配列を渡してそれを3倍にしたいとします。
この時次のようなコードを書いても思った通りの結果にはなりません。
1 2 3 4 5 6 |
$arr = [1, 2, 3]; foreach( $arr as $v ){ $v *= 3; } print_r($arr); |
このコードの表示結果は次の通り
1 2 3 4 5 6 |
Array ( [0] => 1 [1] => 2 [2] => 3 ) |
なぜこういう結果になるかというと foreach で as の後に渡される変数というのは値渡しだから。
値渡しされた変数を変更することは不可能です。
なので思った通りに動かすには foreach で要素変数を参照渡しする必要があるのです。
例えば上のコードで参照渡しするなら次のような感じ
1 2 3 4 5 6 |
$arr = [1, 2, 3]; foreach( $arr as &$v ){ $v *= 3; } print_r($arr); |
as の後の変数を $v から &$v に変えるだけです。
これで次のような思った通りの結果が出ます。
1 2 3 4 5 6 |
Array ( [0] => 3 [1] => 6 [2] => 9 ) |
参照渡しというと関数で使うのが一般的です。
でもそれだけでなくて foreach などの参照を指定できる構文でも使うことができます。
ここまでのまとめ
参照渡しの利用例をもう一度まとめると次の通り
- 関数で参照渡し
例 : 配列などを渡して要素の値を変更する
- foreachループ内で参照渡し
例 : ループ内で配列要素の値を変更するなど
実際に使用する場面は少ないですがこういう使い方もできます。
利用例として思いつくのはこれくらいですが他にも利用方法ってあるんでしょうか?
もし知ってる方いたらコメントなどで教えてください。
ではでは($・・)/~~~