第1回 コードリーディング

ちょっとした経緯で定期的にコードリーディングをすることにした。
満足するまでは続けようと思う。

最初の題材はFuelPHP

とりあえず、リクエストがControllerを呼び出すところまで
追ってみようと思ったけど、
途中に出てくるクラスを調べてたら終わらんかった・・・。

全体をサラッと確認してから、
1つ1つのクラスを追ったほうがいいな。
色々移りながら追うのは効率悪い気がする。

そして、FWを読むのは予想以上に勉強になる・・・。


【リクエスト時の大体の挙動】
コードを追っていく前に軽く確認してみる。
index.php

autoloader.php

appのbootstrap.php

Request::forge()->execute()->response(); でリクエスト処理



【Coreがほぼstaticなクラス】
シングルトンではなく、staticな変数 + staticなメソッドでできている。
これには説明があった。
2011年の記事だけど・・・。
http://fuelphp.com/blogs/2011/05/why-did-you-do-that

「メモリ消費を抑える + グローバルアクセスによって使いやすくするため」らしい。
FWになるなると static と singleton のメモリ消費の差にも気をつけないといけないのか・・・。



【appのbootstrap.php
appのbootstrap.phpスクリプトで以下を実行している。
・coreのbootstrap.php のrequire()
・appの名前空間の定義
環境変数 $env のセット
・Fuelの初期化



【coreのbootstrap.php
coreのbootstrap.phpスクリプトで以下を実行している。
・base.phpのrequire()
・autoload.phpでCoreクラスのオートロード
・vendor の autoload.php でvendorのクラスのオートロード
・register_shutdown_function(), set_exception_handler(), set_error_handler() の設定。


【base.php
便利関数の寄せ集め。
例えば、htmlのエスケープをする e() とかが定義されている。
いちいちインスタンスを生成したり、staticにアクセスしなくてもいいやつはそのまま関数で定義している。
確かに当たり前なんだけど、実装を見ると改めて「そうなんだ」と思う。


【autoloader.php
namespaceの名前とパス、classの名前とパスを管理する。
autoloader.php 自体は index.php で class_alias() を利用して読み込んでいる。
利用するクラスを include していない場合は Autoloader::load() が呼ばれて、include される。
ほとんどCoreモジュールの読み込むだけのシンプルなリクエストでAutoloader::load() が呼ばれる回数は30回程度だった。
init_class() は実際にクラスをinclude()する処理が書いてある。
Fuelではクラスに _init() を実装することで初期化処理をしてくれるけど、その設定も init_class() でやっていた。
オートロードを実装することで、こういった柔軟なロード実装が可能になるのか・・・。
オートロード時は Core と app/classes直下 でロード方法が違う。
Controllerはclasses直下だけど、URLのパラメータを考慮したローディングになっている。


【Fuelの初期化】
Fuel::init('config.php'); で初期化されている。
app/bootstrap.php でしか呼ばれない。
色々やってるけど、config.php の設定を反映させているコードが目立つ。
ob_callback, ob_gzhandler とか知らなかった・・・。


【ログについて】
利用する時は Log::error('msg'); のように利用する。
Logクラス自体は MonoLog というログライブラリをラップしているだけ。
リクエスト時はFW内部で一度 logger() を呼び出していて、logger() 内部でログのインスタンスを生成し、
INFOレベルで 「Creating a new main Request with URI = "action/v1/read/mymethod/100/1001"」のようなログを残す。
logger() 自体は base.php に関数として定義されている(base.php は関数を羅列しただけのファイルでクラスではない)。