可変変数でメソッドを実行した際のFunction name must be a stringを解決する

しばらく特にハマっていたこともなかったので技術関係では久しぶりの更新となる。

現在、いつもとは別口のとある会社さんからシステム開発の依頼を受けて、それをPHPで作っているのだが、その中で頭を悩ませる事態に遭遇した。

URLパラメータごとにクラスとメソッドを振り分けようとして、こいつらを可変変数にしたら、メソッドの可変変数のところで「Uncaught Error: Function name must be a string in /hoge」とエラーが出て久しぶりにハマった。

 

可変変数として使用する配列に、おおよそ以下のような形のざっくりコードでクラスやメソッドを格納していたのだが、

Class My_Class {
	public function mymethod() {
		echo 'test';
	}
}

$class_to_method = array(
	'class' => 'My_Class',
	'method'=> 'mymethod',
);

$instance = new $class_to_method['class'];
$instance->$class_to_method['method']();

いざこれを実行してみたら、$instance->$class_to_method[‘method’]();のところで件のエラーが表示された。

 

毎度おなじみのvar_dump()で$class_to_method[‘method’]の値を出してきても”string(8)”で返って来るし、ワケワカメ。

まるでどこを縦読みみたいな様相で、ラーメンのハネ汁の飛びまくったディスプレイの前で首をかしげた。

 

10分ほどなぜそうなったかを考えてみたりしたが思い当たるフシがない。

シンタックス的なエラーではないので、上記のコードで間違いなく動くはずなのだが・・・。

 

まぁ、そうしたからって言ってどうにかなるわけでもないので、とりあえず色々試してみた。

そして、得た答えは「可変変数でメソッドを実行する場合は、その可変変数は配列を直接参照してはならない」ということ。

 

「関数は文字列でなければなりません。」との通り、これはメソッドに指定した配列の値じゃなくて、配列そのものがメソッド名として評価されているみたいだ。(正直、メソッドなのにFunctionって出ていたので、若干戸惑ったが。)

つまり、上のざっくりコードだと、本来配列に入れたはずの’mymethod’の文字列がメソッド名の文字列として評価されず、$class_to_method[‘method’]という配列そのものがメソッドとして評価されている。

 

なので、この場合は多少効率は悪いが、以下のようにコードを書き直して解決する。

Class My_Class {
	public function mymethod() {
		echo 'test';
	}
}

$class_to_method = array(
	'class' => 'My_Class',
	'method'=> 'mymethod',
);

$instance = new $class_to_method['class'];
$method = $class_to_method['method'];
$instance->$method();

配列そのものを参照するのではなく、通常の可変変数に一旦退避させて、この通常の可変変数よりメソッドを実行する。

これで件のエラーはなくなり、mymethodのメソッドが実行されるようになった。

 

ちなみにクラスについては配列そのものが評価されるということはない様子。

括弧を入れるとどうなるかまでは試してはいないが・・・。同じエラーが出たら同じ方法で解決できると思う、多分。

つか、Functionって出ているあたり、関数もそうなのかもしれない。

 

しばらくWordPressくらいしか触っていなかったので、凄まじく久方ぶりの完全ネイティブなPHPだが、これで当分は飽きることはなさそうだ。

必要とされたシステムそのものも、なかなかおもしろいシステムだと思ったしねw

 

正直、WordPressはもうやり尽くした感があって、いただく仕事も完全な作業と化している。

プラグインならともかくテーマじゃなぁ・・・。

 

WordPressでの作業の合間、ふと鏡で顔を見たら、目が死んでるどころか肌も死人のそれになっていた。(加齢のせいか?草)

 

やっぱり作っていて楽しいのが一番だよ。

カテゴリ

この記事のコメント

コメントはないです。

コメントを残す

メールアドレスが公開されることはありません。