へれへれ追跡の続きです。
今まで見てきたところだと、amfphpはFilterとActionという形で処理のシーケンスを管理しているようです。
kloveさんの後追いになりますが、まずはS2Containerから取得したServiceをどうやってamfphpで読み込んで実行するかをメインに見てまいります。
肝になるAction
グローバル関数function batchProcessFilter(&$amf)(/core/amf/app/Filters.php)の中でGateway->actionsで設定されたActionが実行されます。
そして、AMFObjectクラスのインスタンスの_bodysプロパティ(実体は配列)分ループ、さらにその中でGateway->actionsで設定されたAction分ループです。
Actionもそれぞれグローバル関数で定義されていて、肝は
- function classLoaderAction (&$amfbody)(/core/shared/app/BasicActions.php)
- function executionAction (&$amfbody)(/core/amf/app/Actions.php)
- クラスファイルのインクルードとインスタンス生成
- 処理の実行
処理の実行はクラスファイルのインクルードとインスタンス生成がうまくいっているなら、そのまま実行できるはず。
よって、classLoaderActionを調査です。
classLoaderActionにつっこみ
この関数の中では
- $amfbody->classPathで指定されたディレクトリとファイルの存在確認
- Executiveクラスのstatic関数includeClassでクラスファイルのインクルード
- Executiveクラスのstatic関数buildClassでインスタンスの生成
さて、よくよく考えてみます。
クラスやインスタンスの管理はS2Container.PHP5の機能で行いたいわけです。
S2Baseのお作法でいくなら、このあたりは設定ファイルで行うのです。
問題なのは、classLoaderActionはループで回っているので、何回も呼ばれる可能性があるわけです。
そう考えると、上流のあたりで(gateway.phpが妥当かな)で設定ファイルのインクルードを行って、ここでS2ContainerClassLoaderのimportメソッドでS2Baseのモジュールを読み込みと、__autoload関数の定義。
HackするclassLoaderActionでは、既にクラスが存在しているかどうか確認して、存在しないなら既存の処理、存在しているならインスタンス取得、という流れが自然ですね。
で、一番考えないといけないところは、S2Containerのインスタンスをどう扱うか、です。
diconファイルが複数あってS2Containerが複数必要になるケースって、どうなんだろう。
ServiceがDaoを扱うことが前提である以上、同じDaoのインスタンスが複数発生しうるケースっておおよそ怪しいかな。
ということで、ひとまずこんな風に考えてみました。
S2Baseでつらつらっと作業するとdiconファイルが複数する可能性はあるわけですが(インクルードされない)、やっぱり
- ユニークな名前の統合diconファイルを生成
- ひとつだけS2Containerのインスタンスを生成
- インスタンスの取得はそこから
つまり、グローバル変数にS2Containerをインスタンスを設定して、それを参照してインスタンス生成。
やっぱりこの形かな。
もう少し大きいスコープで見てみると、
- Gatewayクラスのインスタンス生成
- もにゃもにゃ設定等々
- S2Baseの設定ファイル読み込み
- S2Containerのインスタンス生成
- Gatewayクラスのインスタンスのactions['class']を置き換え
- Gatewayクラスのインスタンスのservice()メソッド実行
なんとなく方向性が見えてきましたね。
追跡編はここまでで、そろそろ考えよう編に入れそうです。