先日、こんな事件がありました。
<?php class Hoge public function doSomething() { $func = $this->func; $func(); // これ以降 $func は使われていない } }
このようなコードがあり、これを
<?php class Hoge public function doSomething() { $this->func(); } }
こう書き換えた結果事故った。という事件がありました。
どういうことなのか
一見正しく変更したように見えるコードですが、何がだめなんでしょう。
$func = $this->func; $func()
これが
$this->func()
こうなっただけです。なんか下の書き方も正しそうに見えますよね?
もっとわかりやすく
こうです
$this->func = function() { echo 'やったぜ'; } $func = $this->func; $func();
これの結果はどうなるでしょう?
当然「やったぜ」になります。
では
$this->func = function() { echo 'やったぜ'; } $this->func();
これは?
「やったぜ」になりそうな気がしません。
何が間違いなの?
正しくはこうです
$this->func = function() { echo 'やったぜ'; } ($this->func)();
何が違うのでしょう。
具体的に動くコードで見てみる
わかりましたか?
つまり、 $this->func()
は クラスに実装されたメソッドを呼ぶというコードになるのです。
クラスのプロパティを呼ぶのは $this->func
で、そのプロパティが callable な場合は ($this->func)()
として、さきにプロパティとして解決させてあげてから、それをcallableとして呼ぶ、というように書く必要があるのです。
実はこの ($this->func)()
という書き方、PHP7から使えるようになりました。PHP7以前は、最初に書いたように
$func = $this->func; $func();
と一回変数に置く書き方でしか呼べないので、このコードは正しかったわけです。
PHP7になり Type Hinting 等便利な機能が多数つきましたが、地味にこういう機能もついてたんでしたね。へー。
*1:gistの貼り付け機能をはじめて使ってみた気がする