mapleの動作を見ていく

0=="nonZero" という動作も知らなかった初心者の俺様が新進気鋭のPHPフレームワークMapleの動作を解説してやるぜ!(というか自分用メモ) まあmojaviの使い方もよく知らないわけですが(;´Д`)

全体的な流れ

 htdocs/index.php から Controller。ControllerでRequestからActionが決定される。Actionが配置されているディレクトリの設定ファイルでFilterChainが設定される。で、FilterChainを順番に実行していって、最後にActionを実行する。Actionの返値でどのテンプレートを使うか(リダイレクトするか)が決定され、Actionのプロパティー値やメソッドや、ErrorListというどこかのFilterが設定したかもしれないエラー保存用オブジェクトを使ってテンプレートが展開され、画面が表示される。
 設定するところは Filter(maple.ini)、DIContainer(base.ini)、Action(コード)。あと maple/core にいろんな処理を放り込む。maple/filter にいろんなフィルタを放り込む。

Controller

 DIContainer の設定( base.ini )がされる
 DIContainer から Request が取り出される
 Request からAction が決定される
 DIContainer から ActionChain が取り出される
 ActionChain に Action が追加される
 DIContainer から ConfigUtils が取り出される
 ConfigUtils->execute
 DIContainer から FilterChain が取り出される
 FilterChainにConfigUtilsを与え、Filterを生成する(だいたい maple.ini のセクションの順番に生成)
 Filter が順次実行され、クリアされる(だいたい Covert,Validate,Action,View の順番)
 ConfigUtilsがクリアされる

ConfigUtils

 DIContainer から ActionChain が取り出される
 ActionChain から現在の Action名を取り出し、設定ファイルのパスを計算し、フィルタ名と値を取り出す

Filter

 maple.ini の記述順だが実行されるのは preFilter を順番に→postFilterを逆順に なので View の postFilter が最後に実行されたりする。またActionは常に最後に追加される

Filter_Convert

 maple/core/ConvertManager に maple.ini の設定を与えて実行

ConvertManager

 maple/converter を使って、与えられた設定を順番に実行していく
 入力値はDIContainerでRequestを取り出して、RequestからgetParamater
 Convertした値はRequestにsetParameter
 Convertルールは実行時に与えられる

Filter_Validate

 maple/core/ValidatorManager に maple.ini の設定を与えて実行

ValidatorManager

 maple/validator を使って、与えられた設定を順番に実行していく
エラーを報告するクラスErrorListはActionChainから取り出す(getCurErrorList)
 ActionChainはDIContainerから取り出す
 チェック対象はDIContainerからRequestを取り出す
 チェックルールは実行時に与えられる

Filter_Action

 action が DIContainer内のActionChainから取り出される
 actionに maple.ini の設定値が設定される
 設定値は ref: で始まっている場合は DIContainerから取り出されたもの、それ以外はそのまま(文字列として)
 さらにactionに DIContainer内のRequestから取り出された値が設定される
 設定は maple/core/BeanUtils::setAttributes にて行われる
 そしてエラーがなければaction->executeが実行され、view値が取り出される
 action->executeにより返されたview値は DIContainer内の Responseに setView される

BeanUtils

 setAttribute は、ハッシュのキーXXXに対応するsetXXXメソッドがあれば、ハッシュの値を引数としてそのメソッドを呼ぶことでオブジェクトにプロパティーを設定する

Filter_View

 DIContainerのResponseからgetViewで取り出した値(文字列 $template)を元に表示を行う。
 $templateが location: で始まっていればリダイレクト( header( Location: url ) )
 違う場合はmaple/core/Smarty4Maple をnew して
  DIContainerのActionChainから取り出したactionとErrorListと
  DIContainerから取り出したTokenと
  $templateの値を、それぞれ専用メソッドでセットし、
 テンプレートの計算結果を取り出す
 ヘッダなどはResponseから取り出す
 結果をprintする

Smarty4Maple

 まあsmartyの単純なラッパー

感想

いじっていいところといけないところの切り分けがよく分からない。mapleがバージョンアップしたときとかに簡単に上書きできるような仕組みになっているのだろうか?
グローバルなデータはDIContainerを使ってやりとりしている。のでメソッド定義だけ見ても、どこでデータをやりとりしているか分からない。
だいたいDIContainerってなんだ?「設定ファイルで内容を記述できる汎用Factory・Builderクラス」「名前で設定済みオブジェクトを取り出せる」あたりか? DIContainerのメリットってなんだろう? mapleコード中でオブジェクトを生成する際に DIContainerから生成・呼び出しているもの、newしているもの、Factoryクラスから呼び出し・生成ているもの、がある。使い分けがよく分からない。globalで設定したり、それぞれにFactory作るのとの違いは?
iniファイルは簡潔でFilterの順番とそのパラメータを同時に設定できる優れもの。でも表現力に乏しく(配列や多階層ハッシュなどは難しく、基本的にスカラー値しか表現できない)、mapleは記述を簡略にするために特殊な表記法を用いていたりするが…うーん XMLは重すぎだと思うし… YAML辺りがよさげだけれど。bogoYAMLってのもあった。maple.ini、base.ini 程度の定義なら、いっそコードで設定するって手も。
ActionChainの使い方がよく分からない。