PHPのマジックメソッド

PHPのマジックメソッドは、フレームワーク自身に手を入れたりしない限りは、普段はあまり
使わないメソッドと思うけど、今回はちょっとこれを使って、モデルを分割出来ないか試してみた。

というのも、YiiやLaravelなどのRails派生型のMVCデザインパターンだと、モデル(ロジック)
が大きくなることが多いかなと思ったので。
(コントローラが大きくなる場合は、たぶん、設計を見直していけばモデルの方に押し付けられると
思うので、結局はモデルに負担が来るかと思う)

さて、モデルは、継承とか委譲でうまく分割していければいいんだけど、案外、フラットな作りで
メソッドがたくさんある場合は、きれいにいかない。そこで(いいやり方かどうかわからないけど)
コントローラとビューを分けるような感じで、メソッドの出入り口をマネージャで、個々のロジックを
ロジックファイルで分けて、それをマジックメソッドでつなぐようにしてみた。

 具体的には、モデルにあるXXXManager.phpクラスに、次のメソッドを実装。

public function __call($name,$parms) {
if (preg_match("/^action/",$name)) {
$cname = get_class($this);
if (preg_match("/^(.*)Manager$/",$cname,$matches)) {
$dname = $matches[1];
$dir = __DIR__ . "/" . $dname;
$fname = $dir . "/" . $name . ".php";
if (file_exists($fname)) {
return require $fname;
}
}
}
return parent::__call($name,$params);
}

 これはつまり、モデルの名前が
XXXManager.php
とした場合、XXXManager.phpにYYYメソッドがないと、
XXXディレクトリの中のYYY.phpファイルを見つけて、それがあればそれを読み込んで実行する、
という作り。
 ディレクトリ構造的には

XXXManager.php
XXX/YYY.php

 上記の__callメソッドの中でrequire文があるけど、require_onceだと一回しか読み込まないの
でダメ。また、ロジックファイル(上記例ではYYY.phpファイル)中で$thisによりXXXManagerのイン
スタンスを参照しているので、YYY.phpファイルはベタにメソッドの中身のみを記述する。

 決して良いコードとは言えないと思うけど、PHPだとこんな感じの実装になると思う。
 PHPって不思議な言語だなぁと思う。

 一つポイントは、__callメソッドをオーバーライドする場合は、上記のようにparent::__callで
親クラスのものを呼び出すようにすること。