PHPのcall_user_func()での参照渡しに注意


どうもよくわからんのでメモ。

参照渡しとは?

関数に値を渡す通常の方法。

<?php

$i = 0;

test($i);

print $i; // 0を出力。$iの値そのものは変わらない

function test($int){
  $int++;
}

?>

参照渡しにする。(関数の定義の引数の部分に&をつける。)

<?php

$i = 0;

test($i);

print $i; // 1を出力。$iの値がかわった!

function test(&$int){
  $int++;
}

?>

通常の関数の引数は、渡された変数の値のみが渡されるが、参照渡しをすると変数そのものが渡されるので、このような挙動になる。

PHP5での仕様変更

ここまでは、特に問題はない。

しかし、PHP4では、以下のように呼び出し側でも参照渡しの指定ができたが、これはPHP5ではphp.iniを変えないと動作しない。

<?php

$i = 0;

test(&$i); // 呼び出す際に&をつける

print $i; // 1を出力。$iの値がかわった!

function test($int){
  $int++;
}

?>

これは実際、そうするべきだと思う。

なんで呼び出し側で参照渡しをできるようにしていたのか、よくわからんので、改善だと思う。

が!問題はここから!

call_user_funcを使用した際の参照渡し

以下のようにcall_user_funcを使用すると、関数側で参照渡しするよう指定していても参照渡しされないばかりか、警告が出る!

<?php

$i = 0;

call_user_func('test', $i);

print $i; // 0

function test(&$int){
  $int++;
}

?>

出力結果

Warning: Parameter 1 to test() expected to be a reference, value given in...

ためしに、call_user_func(‘test’, &$i); としたら予想通り以下のエラー。

Deprecated: Call-time pass-by-reference has been deprecated in

なんじゃそりゃ!?

解決策

いろいろ試した結果、以下のような方法なら大丈夫なようだが、全く納得がいかない。

call_user_func_array() を使用する

<?php

$i = 0;

call_user_func_array('test', array(&$i));

print $i; // 1を出力。$iの値がかわった!

function test(&$int){
  $int++;
}

?>

関数名を変数に代入してコールする

<?php

$i = 0;

$func = 'test';

$func($i);

print $i; // 1を出力。$iの値がかわった!

function test(&$int){
  $int++;
}

?>

たまたま、今のバージョンで警告が出ていないだけなのか?
もしそうなら、 call_user_funcしたいときは、どうやって参照渡しするんだ?

参考


関連する記事

One thought on “PHPのcall_user_func()での参照渡しに注意

  1. Pingback: プログラミングメモ

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>