• 締切済み

PHPでrailsのbefore_filterを再現したいのですが

初めまして。当方PHP初心者です。 標題の通り、PHPでrailsのbefore_filterのような機能を再現できないでしょうか。 要するにクラス内にAメソッド、Bメソッド、Cメソッド、Dメソッドが存在していて、 Bメソッド、Cメソッド、Dメソッドを実行する前に必ずAメソッドを実行させたいのです。 実現できる関数を探してみたのですが、どうにも見つかりませんでした。 皆様のお知恵を拝借したいです。 どうぞ、よろしくお願いします。

みんなの回答

回答No.1

Ruby On Railsは、Ruby言語で開発されたWebアプリケーションフレームワークですので、 素のRubyで存在しているパターンというわけではないんじゃないでしょうか。 PHPでもまた、素のPHPで実現できるものではなく、フレームワークに機能として含まれている場合がある(ソレもアクセス手段を限定的にした場合に動作する)、程度のものだと思います。 PHPはRubyほど柔軟な言語ではないので、ソレを標準的にどこでも利用できるようにするとしたら、PHPの言語自体のソース(C言語作られた元のソース)を紐解いて修正するなり、Extensionを作成する(やっぱりC言語)しかないと思います。 ただ、意図する動作に「近いもの」を実現する方法としてはいくつかあります。下記はその一例です。 <?php class Test{ protected $before_filter = 'A'; protected function A(){ echo "hoge"; } protected function _B(){ } protected function _C(){ } protected function _D(){ } public function __call($name, $param){ $name = "_{$name}"; if(method_exists($this, $name)){ if(is_callable(array($this, $this->before_filter))){ call_user_func(array($this, $this->before_filter)); } return call_user_func_array(array($this, $name), $param); } return null; } } $test = new Test(); $test->B(); $test->C(); $test->D(); ?> このようにすれば近い動作はします。 これは、 必要なメソッド名の前に「_(アンダースコア)」をつけたものを作成し、外側の呼び出しでは「$test->C()」というように「_」をはずして呼び出します。 当然存在しないメソッドを呼び出していますので、通常エラーになってしまいますが、PHPのオーバーロードの、マジックメソッドである「__call」にて、存在していないメソッド名と引数に指定されたものを取得します。 そして、取得したメソッド名に「_」を付加し、メンバ変数$before_filterで指定したメソッドをcall_user_func関数で呼び出した後に、call_user_func_array関数にて、それぞれ動的にメソッドを呼び出しています。 マジックメソッドや、call_user_func関数などに関しては、PHPマニュアルや、その他解説サイトなどで詳しく説明されています。