CakePHPのソースを読む 07

2014-01-13
PHP
CakePHP

さて、SPLの匂いが漂ってきました。

1
spl_autoload_register(array('App', 'load'));

なんだ、なんなんだ!spl_autoload_registerって何なんだ! spl_autoload_register - PHP Manual
ん?第一引数に配列を受け取るとは書いてない・・・。 わからん。しょうがないのでソースを読む。PHPのバージョン5.5.7のソース内 ext/php_spl.cの499行目当たりを見ると

1
2
3
4
5
6
7
8
9
499             if (Z_TYPE_P(zcallable) == IS_ARRAY) {
500 if (!obj_ptr && alfi.func_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
501 if (do_throw) {
502 zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Passed array specifies a non static method but no object (%s)", error);
503 }
504 if (error) {
505 efree(error);
506 }
507 efree(func_name);

うーむ、Cの能力が足りてなくて読み解けないけど、察するに配列の引数1番目のクラスの引数2番目のstatic関数を受け取れるらしい。 今回の例で言えば、App::loadメソッドを__autoloadの関数として登録するということらしい。

App:loadメソッドが__autoloadとして使われるというのは、どういうことなのか・・・? 情弱は、疑問の渦へ・・・   クラスのオートローディング - PHP Manual 要するに! includeの自動化である!

肝は、「ク・ラ・ス」のオートローディングという所。 つまり、インスタンスをnewするタイミングで、__autoload()が呼び出される。
ここまでの話を総合すると、以下のように理解することが出来る。

  1. CakePHPでは、App:load関数を__autoloadとして登録している。

  2. App:usesされた「クラス名、場所」はAppクラスの$_classMap配列へ追加される

  3. $_classMapへ追加されたクラスは、instance化される段階でautoloadによって、includeされる。(予想)

3番めの予想が正しいことを確認するには、App:load関数を読み解く必要がある。 というわけで、ソースを貼り付けようと思ったが、貼り付けても意味は分かりづらいのでやめた。 というわけで、最低限の関数定義はこちら。

1
public static function load($className) 

つまり、例えば CakePHPにおいてModel/Hoge.phpに書いてあるHogeクラスのインスタンスをnewした場合。

(1) __autoload()が呼び出されApp:load(‘Hoge’)が実行される。 -—–ここから下はload関数の処理——
(2) Appのメンバ変数 $_classMap配列に該当クラス名のキーが存在するかをチェック。無ければfalse返して終わり。
(3) クラス名に「..」が含まれていないかチェック。あったらfalse返して終わり。
(4) ユーザのappディレクトリ、Cakeのappディレクトリ、CakeのLIBRARYの順番にpath + ディレクトリ名 + クラス名 + .php でファイルの存在チェックをする
(5) ファイルが見つかったら、includeして終了 ※ちなみに、ディレクトリ名の部分にPlugin名 + ドット + ディレクトリ名を指定すると、Pluginのロードも出来るようです。いつ使うのかな??

というわけで、CakePHPはユーザのappクラス配下のファイルを第一番にloadするようにautoloaderが動くのが分かりました。 ここを乗り越えると、bootstrap.phpの難しいところは大体終わりです。 次回は、bootstrap.phpの残り部分を読みます。