コンテンツにスキップ
Nibiru docsv0.9.2

コントローラー

Nibiru コントローラーの作成 — アクションライフサイクル、View::assign、および生産コードからのパターン。

Stable Reading time ~ 2 min Edit on GitHub

ニビルコントローラーは、Nibiru\Adapter\Controller を拡張したクラスで、application/controller/<name>Controller.php に存在し、URL が /<name>/... のようなものにアクセスすると Dispatcher によって自動的に読み込まれます。

<?php
namespace Nibiru;
use Nibiru\Adapter\Controller;
class productsController extends Controller
{
public function pageAction() {
View::assign([
'title' => 'Products',
'products' => $this->loadProducts(),
]);
}
public function navigationAction() {
JsonNavigation::getInstance()->loadJsonNavigationArray();
}
public function detailAction() {
$id = (int) ($_REQUEST['id'] ?? 0);
View::assign(['product' => $this->loadProduct($id)]);
}
private function loadProducts(): array { /* ... */ return []; }
private function loadProduct(int $id): array { /* ... */ return []; }
}

ディスパッチャがコントローラを呼び出すと、以下の固定の順序でメソッドを呼び出します:

  1. navigationAction() — グローバルメニュー、パンくず、役割に応じたナビゲーションを設定します。
  2. <動詞>Action()?_action=<動詞> がセットされている場合や、URL のセグメントにアクション名がある場合のみ実行されます。
  3. pageAction() — レンダリングの直前に呼び出されます。

navigationAction()pageAction() は、常に呼び出されます。未知のアクションでも同様です。これは便利ですが(チェックする必要がありません)、アクションが排他的であると仮定すると驚くことがあります。

View::assign(['key' => $value, ...]) はデータがテンプレートに到達する方法です。これは静的であり、必要なだけ呼び出すことができます — 後の呼び出しは前のものを上書きします。

View::assign(['title' => 'Products']);
View::assign(['products' => $list]);
// In templates/products.tpl:
// {$title} → "Products"
// {$products} → the array

ベースコントローラーからの便利ヘルパー:

$this->getRequest('id', false); / $_REQUEST['id'] ?? false
$this->getPost('email', ''); / $_POST['email'] ?? ''
$this->getGet('page', 1); / $_GET['page'] ?? 1
$this->getServer('REQUEST_URI'); / $_SERVER['REQUEST_URI']
$this->getFiles('upload'); / $_FILES['upload']
$this->getSession('auth'); / $_SESSION['auth']

これらは存在する理由は、Controllerfinalに耐えられるように設計されていることです:テストで子クラスを置き換えてモックすることができます。

アクション内でリダイレクトするには:

View::forwardTo('/login'); / 302 to the URL, exits
View::forwardToJsonHeader(); / sets Content-Type: application/json

forwardToJsonHeader() は、JSON エンドポイントの標準的なパターンです。ヘッダーを設定し、data を割り当ててから返す。その後、表示層が残りの処理を行います。

コントローラーごとに複数のアクション

Section titled “コントローラーごとに複数のアクション”

Nibiruはコントローラーごとに任意の数のアクションをホストすることができます。プロダクション環境のTPMS erpControllerには、pageActionnavigationAction、さらにsyncActionstatusActiondryRunActioncancelActionなどがあります — 各アクションは?_action=syncまたは/erp/syncで呼び出されます。

// /erp/sync → $_REQUEST['_action'] = 'sync'
public function syncAction(): void
{
View::forwardToJsonHeader();
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
View::assign(['data' => ['success' => false, 'error' => 'POST method required']]);
return;
}
$result = AlphaplanSyncService::getInstance()->syncAbDocuments();
View::assign(['data' => $result]);
}

コントローラーは薄いです。ほとんどのロジックはモジュールとそのプラグインに存在すべきです:

namespace Nibiru;
use Nibiru\Adapter\Controller;
use Nibiru\Module\Users\Plugin\User;
class loginController extends Controller
{
private User $user;
public function __construct() {
parent::__construct();
$this->user = new User();
}
public function authAction() {
if (!$this->user->isAuthorized()) {
View::assign(['loginForm' => $this->user->loginForm()]);
} else {
View::forwardTo('/index');
}
}
}

この委譲パターンは、デモンストレーションアプリケーション全体で一貫しています:コントローラーがオーケストレーションを行い、モジュールが作業を行います。

多言語 / コンテンツ管理システム(CMS)ドライブコンテンツ

Section titled “多言語 / コンテンツ管理システム(CMS)ドライブコンテンツ”

prod.maschinen-stockert.de からのパターン — コントローラー パスでキー付けされた CMS テーブルからすべてのページ上のテキストを読み込む:

public function pageAction() {
$controllerPath = $this->getController()
. '/' . $this->getRequest('_action', 'page');
$texts = Cms::init($this->getController())
->loadCmsTemplateTextsByControllerPath($controllerPath, $this->language);
foreach ($texts as $t) {
View::assign([
$t['cms_template_texts_text_identifier'] =>
$t['cms_template_texts_text_content']
]);
}
}

結果:非開発者はコードに触れずにコピーテキストを変更できます。CMSモジュールがテーブルとエディタUIを所有し、コントローラは単に文字列を読み込みます。

CLI はコントローラーとそのテンプレートを一発で生成します:

Terminal window
./nibiru -c products

application/controller/productsController.phpapplication/view/templates/products.tpl

両方とも正規のスケルトンで埋められています。書く準備ができています。