Bootstrap & Dispatcher
Nibiruリクエストがindex.phpを経てディスパッチャに到達し、その後あなたのコントローラーにどのように流れることか。
ニブルのリクエストは3つのファイルを1回通過します:index.php、core/framework.php、およびcore/c/dispatcher.php。それらをその順序で読み込むと、すべてがわかります。
index.php
Section titled “index.php”<?phprequire_once 'core/framework.php';これが全体のファイルです。index.phpはウェブサーバーにターゲットを提供するだけです。
core/framework.php
Section titled “core/framework.php”framework.php は、依存関係の順序でフレームワークのクラスを読み込みます。設定、レジストリ、ルーター、エンジン、オートローダー、すべてのデータベースドライバー、すべての28種類のフォームタイプ、ビュー、コントローラー、モジュール、認証、デバッグ、表示 — そして最後に以下を実行します:
Nibiru\Dispatcher::getInstance()->run();その単一の呼び出しは、アプリケーションのハートビートです。
Dispatcher::run()
Section titled “Dispatcher::run()”簡略化された流れ:
public function run() { date_default_timezone_set(Config::getInstance()->getConfig() [View::NIBIRU_SETTINGS]['timezone']);
if (Config::getInstance()->getConfig() [self::CONFIG_GENERATOR_SECTION][self::GENERATOR_DATABASE]) { new Model(false); / 1. (re)generate models from schema }
Router::getInstance()->route(); / 2. parse the URL Auto::loader()->loadModelFiles(); / 3. load model files Auto::loader()->loadModules(); / 4. load module classes
$tpl = Router::getInstance()->tplName(); $controllerFile = __DIR__ . "/../../application/controller/{$tpl}Controller.php";
if (is_file($controllerFile)) { / 5. controller file exists require_once $controllerFile; $class = "Nibiru\\{$tpl}Controller"; $controller = new $class();
if (array_key_exists('_action', $_REQUEST)) { $action = $_REQUEST['_action'] . 'Action'; $controller->navigationAction(); if (method_exists($controller, $action)) { $controller->$action(); / 6. optional named action } $controller->pageAction(); } else { $controller->navigationAction(); $controller->pageAction(); }
Display::getInstance()->display(); / 7. render Smarty } else { / 8. soft 404 — render the configured error controller }}アクションシーケンス
Section titled “アクションシーケンス”すべてのリクエストが同じ3つのステップを経る場合、?_action=foo が設定されているときです。
navigationAction()— メニュー、パンくずを設定します。fooAction()— 名前付きアクションを実行します。pageAction()— テンプレートデータを最後に割り当てます。
_action 無しでは、ステップ 1 とステップ 3 のみが実行されます。
これは、ステートレスなレンダリング時ロジックは pageAction() に含まれるべきであり、ナビゲーションデータは navigationAction() に含まれるべきであるということを意味します。それが労力の重複に感じさせても、同じプロジェクト内の2つのコントローラーともに navigationAction() を持つのは正しいです。
ソフト404
Section titled “ソフト404”マッチしたコントローラー ファイルが存在しない場合、Nibiru は ソフトウェア 404 をレンダリングします — 200 OK を返し、[ENGINE] error.controller(デフォルト: error)で指定された名前のコントローラーを表示します。これは意図的な動作です:これにより、サーバー レベルの構成なしに美しいエラーページを提供できます。
実際の 404 Not Found HTTP コードを使用するには、エラーコントローラーで設定します。
public function pageAction() { http_response_code(404); View::assign(['title' => 'Lost in the void']);}Auto::loader()
Section titled “Auto::loader()”コントローラーが構築される前に2つのオートローダーが実行されます:
loadModelFiles()はapplication/model/をスキャンし、そのディレクトリ内のすべての.phpファイルをインクルードします。生成されたモデルは名前空間パッケージではなくフラットなファイルなので、これは単純なrequire_onceループです。loadModules()はapplication/module/<name>/を走査し、各モジュールのメインクラスとそのトレイト、プラグイン、インターフェースファイルを読み込みます。レジストリは同時に各モジュールの設定 INI をインデックスします。
両者は、[SETTINGS] modules.path 等の設定されたパスを使用しているため、環境ごとに上書きすることができます。
SEO対応のURL処理
Section titled “SEO対応のURL処理”コントローラーの解決前に、Router::route() は handleSeoUrls() を実行します。このメソッドは /controller/<slug>/<id> 形式の URL(2 番目のセグメントが既知のアクションではなく、3 番目が数値である場合)を検出します。これらの URL は内部的に /controller/detail/ にリライトされ、$_REQUEST['id'] と $_REQUEST['slug'] が設定されます。詳細については Routing を参照してください。
ディスパッチャーをオーバーライドする場合
Section titled “ディスパッチャーをオーバーライドする場合”ほとんどありません。クリーナーの拡張ポイントは次のとおりです:
- カスタムエラーコントローラー —
[ENGINE] error.controllerを設定します。 - プリコントローラーフック — オブザーバーを登録するモジュールを読み込み、その後
navigationAction()内でアタッチします。 - cron スタイルのエントリ —
nibiruCLI を使用してフレームワークをヘッドレスで実行し、代わりにindex.phpを使用します。