アーキテクチャ (MMVC)
モジュール、コントローラー、ビュー、モデル、レジストリ、ディスパッチャーがそれぞれ他に回る関係です。
NibiruはMMVC:Model — View — Controller — そして2つ目のMがModuleです。最初の3つは一般的ですが、2つ目のMがNibiruに独特な風味を与えます。
30秒のメンタルモデル
Section titled “30秒のメンタルモデル” ┌──────────────┐ │ Browser │ └──────┬───────┘ │ HTTP ▼ ┌──────────────┐ │ index.php │ └──────┬───────┘ │ require ▼ ┌──────────────┐ │ framework.php│ ◀── boots Config, Router, Engine, Smarty, └──────┬───────┘ all 28 form types, DB drivers, Auth. │ ▼ ┌──────────────┐ │ Dispatcher │ └──────┬───────┘ │ ┌───────────────┼─────────────────┐ ▼ ▼ ▼ ┌────────┐ ┌──────────┐ ┌───────────┐ │ Router │ │ Modules │ │ Auto │ └────────┘ └──────────┘ │ loader │ └───────────┘ │ ▼ ┌─────────────────────────────┐ │ applicationController.php │ │ navigationAction() │ │ <_action>Action() │ │ pageAction() │ └──────────────┬──────────────┘ │ View::assign(...) ▼ ┌──────────────┐ │ Smarty │ templates/<ctrl>.tpl + shared/* └──────────────┘1. コントローラー (application/controller/)
Section titled “1. コントローラー (application/controller/)”コントローラーは、Nibiru\Adapter\Controller を拡張するクラスです。ディスパッチャーは、すべてのリクエストに対して固定のシーケンスを呼び出します:
navigationAction()— メニュー/パンくずデータを設定します。<_action>Action()— 仅当?_action=fooが設定されている場合にのみ。pageAction()— 最終的なレンダリング時データの割り当て。
すべての3人が戻ったら、Display::display() は割り当てられた変数を Smarty に渡します。
2. ビュー (application/view/templates/)
Section titled “2. ビュー (application/view/templates/)”Smarty .tpl ファイル。ディスパッチャは <controller>.tpl を自動的に解決します;ネストされたアクションは templates/<controller>/<action>.tpl の下に置かれます。View::assign(['x' => ...]) で渡されたすべての変数は {$x} として利用できます。
3. モデル (application/model/)
Section titled “3. モデル (application/model/)”モデルは 自動生成 され、データベーススキーマから Model::__construct(false) によって生成されます — 1つのテーブルにつき1つのPHPクラスです。これらは Nibiru\Adapter\<Driver>\Db を拡張し、CRUDヘルパーを公開しています。生成されたモデルを手で編集し、再生成を無効にするには [GENERATOR] database = false を設定します。
4. モジュール (application/module/<name>/)
Section titled “4. モジュール (application/module/<name>/)”A モジュールはその自らのトレイト、プラグイン、インターフェース、および設定をバンドルします。Registry は各モジュールの settings/*.ini を自動的に発見し、解析された構成を Registry::getInstance()->loadModuleConfigByName('users') 経由で公開します。モジュールは observer パターン を実装して、システムの他の部分がオブザーバーをアタッチし、状態変化に反応できるようにすることができます。
5. コズモスを結ぶシングルトン
Section titled “5. コズモスを結ぶシングルトン”| シングルトン | ジョブ |
|---|---|
Config::getInstance() | settings.<env>.ini を読み込み、モジュールの設定をマージします。 |
Router::getInstance() | URL をコントローラー/アクション/パラメータに解析し、SEO 形式の URL を認識します。 |
Registry::getInstance() | モジュールの発見と設定のキャッシュを行います。 |
Dispatcher::getInstance() | コンダクターです。dispatch::run() はアプリケーションのハートビートです。 |
View::getInstance() | Smarty をラップします。View::assign() はグローバルテンプレート変数のインボックスです。 |
なぜMMVCなのか、MVCではないのか?
Section titled “なぜMMVCなのか、MVCではないのか?”シンプルなMVCは、コントローラーがロジックを共有し始めるまで機能します — 認証チェック、フォームファクトリー、サードパーティAPIクライアントなど。一般的な回答はサービス + DIコンテナですが、これは素早くプロトタイピングするためのフレームワークには多すぎる儀式です。
Nibiruの回答: モジュール。モジュールはドメイン(users, cms, analytics, tpms-quotes)を「所有」し、プラグインコントローラーを通じてそのサービスを公開します。これらのコントローラーは直接インスタンス化できます:
// In a controller$user = new \Nibiru\Module\Users\Plugin\User();if (!$user->isAuthorized()) { View::forwardTo('/login');}モジュールは、その設定、データベーステーブル、テンプレート、フォームを所有しており、単体で削除可能です。
オブザーバパターンの実践的な使用法
Section titled “オブザーバパターンの実践的な使用法”一部のモジュールは SplSubject を実装しているため、他のコードがイベントに反応できるようにする。デモンストレーションでは、prod.maschinen-stockert.de 上の analytics モジュールがこれを行っている:任意のコントローラーは attach() でトラッカー(Matomo プラグイン)をアタッチし、analytics モジュールはページビューごとに notify() する。コントローラーは存在するトラッカーについて何も知らない。
class Analytics implements \SplSubject { private \SplObjectStorage $observers; public function __construct() { $this->observers = new \SplObjectStorage(); } public function attach(\SplObserver $o): void { $this->observers->attach($o); } public function detach(\SplObserver $o): void { $this->observers->detach($o); } public function notify(): void { foreach ($this->observers as $o) { $o->update($this); } }}フレームワークに意図的に含まれていないもの
Section titled “フレームワークに意図的に含まれていないもの”- DIコンテナなし。 シングルトンとプラグインで十分です。
- ORMなし。 モデルはスキーマから生成され、クエリは
Dbアダプターまたはアクティブなドライバーを介した生のSQLを使用します。 - Twig/Bladeのトリックを通じたテンプレート継承なし。 Smarty
{include}が構成単位です。 - イベントバスなし。
SplSubject/SplObserverは第一級です。 - ファーストクラスのバックグラウンドジョブなし。 CLIがスケジューラです — cronやsystemdタイマーからドライブします。
学ぶことが少なく、出荷することが多い。
次にどこへ行くか
Section titled “次にどこへ行くか”- Bootstrap & Dispatcher — コードでのライフサイクル。
- Routing — URL → コントローラーのマッピング規則。
- Modules — 最初のモジュールを作成する。