設計思想

設計判断の原則と考え方。

3つの原則

Naifyの設計判断は、次の3原則に集約されます。

1 コードを読めばわかる
2 責務を明確にする
3 PHPがわかれば使える

原則1:コードを読めばわかる

暗黙挙動より明示を優先します。処理の流れはソースコードを上から読むだけで追跡できる形を目指します。

原則2:責務を明確にする

Routerはルーティング、Controllerはユースケースの調停、BaseControllerはフロー制御と共通前処理に寄せます。何がどこにあるかを役割で探せるようにします。

原則3:PHPがわかれば使える

独自DSLや固有構文を増やしすぎません。標準的なPHPのクラス、関数、インターフェースを理解していれば読み始められるようにします。

優先すること
明示的な初期化
依存関係が見える組み立て
責務境界が見えるディレクトリ設計
増やしすぎないこと
マジックメソッド依存
オートワイヤリング前提
属性での暗黙ルーティング

ミドルウェア論

NaifyはPSR-15相当のミドルウェア基盤を持っていますが、そこへ積極的にビジネスロジックを載せる方針は取っていません。MVCの中で整理できるものはMVCの中に残します。

積極採用しない理由

  • MVCのライフサイクルで大半の処理が収まる
  • ミドルウェアへ業務ロジックを書き始めると、責務の所在が曖昧になりやすい
  • 実行順の追跡コストが増えやすい
  • FWごとのセッションや設定に依存し始めると、PSR準拠のメリットが薄くなる
推奨用途MVCに置きたいもの
CORSヘッダー付与
セキュリティヘッダー
アクセスログ
認証・認可の判定
業務ロジックの分岐
画面やJSONの内容生成
認証を共通化したい場合は、ミドルウェアより BaseController::onActionBefore() に寄せる方が、プロジェクトの流れを追いやすいです。

PSRとの疎結合

NaifyはPSRを参考にしていますが、アプリ開発の主軸はPSR middlewareに置いていません。

NaifyはPSR-7のRequest / Responseを内部で扱っていますが、アプリコードから直接触ることは標準にしていません。代わりに RequestContext を標準の窓口にしています。

PSR-7 Request → RequestContext → Controller

これにより、Controllerは getParam() や getUrlParam() のような単純なAPIに集中できます。PSR実装の差し替えもアプリコードへ波及しにくいです。

//普段のコード
$id = $this->context->getUrlParam('id');
$name = $this->context->getParam('name', '');

//必要なときだけPSRを取り出す
$request = $this->context->getPsrRequest();
$response = $this->context->getPsrResponse();

echoを標準にする理由

Naifyのデフォルトは、Controllerが自分で出力する方式です。Responseオブジェクトを複数レイヤで加工するより、描画やJSON出力の責務をController側へ寄せた方が、読み順が崩れにくいです。

Initial Architecture Lock

設計を文書だけで終わらせず、コード構造に固定するという考え方。特にBaseControllerは、そのプロジェクトで「どこに何を書くか」を最初に固定する役目を持ちます。

Naify Core
FWが提供する骨格。HTTPの入口と処理順を固定します。
↓
BaseController Policy
認証、出力、前後処理のルールをここに固定します。
↓
Feature Controllers
各画面やAPIの具体実装。BaseControllerの前提に従って書きます。
↓
Service / Domain Logic
業務ロジック。FWに依存しない純粋なPHPクラス。
先送りする設計
とりあえず作る
あとで整理する
ルールが散らばる
最初に固定する設計
BaseControllerに落とす
全員が同じ入口を使う
構造が崩れにくい

BaseController戦略

BaseControllerは1つの神クラスにまとめるより、用途ごとに薄く分けた方が読みやすいです。ここで大切なのは、共通前処理の入口を固定しつつ、責務を抱え込みすぎないことです。

  • Web用: Twig出力や画面向け共通処理
  • API用: JSON出力やAPI向け共通処理
  • 認証済み用:認証済み画面だけが持つ前処理
具体的な置き方や実装例は リクエストハンドラとMVC にまとめています。ここでは「薄く分けて入口を固定する」という設計方針だけを押さえればよいです。