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

モデル

Nibiruは、データベーススキーマからモデルクラスを自動生成する方法と、それらを拡張する方法について説明します。

Stable Reading time ~ 2 min Edit on GitHub

Nibiruのモデル層はスキーマファーストです。手でモデルを書くことはありません — フレームワークはデータベースを読み取り、起動時に各テーブルごとに1つのPHPクラスを生成します。

[GENERATOR] database = true が INI ファイルに指定されている場合、ディスパッチャは各リクエストで new Model(false) を実行します。これにより:

  1. アクティブなドライバーに接続します。
  2. 設定されたデータベース内のテーブルをリスト表示します(PGの場合: information_schema.tables、MySQLの場合: SHOW TABLES)。
  3. 各テーブルについて、application/model/<table>.php にクラスを作成し、該当する Db アダプターを拡張し、列を記述した TABLE 定数を埋め込みます。

再実行は安価です:ジェネレーターはスキーマが変更された場合のみ上書きするため、チェックインされたモデルは手で書いたメソッドを保持します*ただし、最初の実行後 database = false を設定すると。

[GENERATOR]
database = true ; regenerate models on each request
database.overwrite = true ; if false, generator won't touch existing files

本番環境では database = false を設定して、モデルが毎回リジェネレートされないようにします。

users テーブルに user_id, user_login, user_pass, user_email という列がある場合:

<?php
namespace Nibiru\Model;
use Nibiru\Adapter\MySQL\Db;
class users extends Db
{
const TABLE = [
'table' => 'users',
'field' => [
'user_id' => 'user_id',
'user_login' => 'user_login',
'user_pass' => 'user_pass',
'user_email' => 'user_email',
],
];
public function __construct() {
self::initTable(self::TABLE);
}
}

Db アダプターは、Pdo::(またはアクティブなドライバー)を介して単純な CRUD ヘルパーを提供します。

$users = new \Nibiru\Model\users();
// Read by primary key
$row = \Nibiru\Pdo::fetchRowInArrayById('users', ['user_id' => 42]);
// Read all
$all = \Nibiru\Pdo::fetchAll('SELECT * FROM users WHERE user_account_active = 1');
// Insert
\Nibiru\Pdo::insert('users', [
'user_login' => 'marduk',
'user_email' => 'marduk@nibiru.local',
]);
// Update
\Nibiru\Pdo::update('users',
['user_email' => 'new@nibiru.local'],
['user_id' => 42]);
// Delete
\Nibiru\Pdo::delete('users', ['user_id' => 42]);

生成されたクラスはプレーンな PHP クラスです — 適便にメソッドを追加してください:

namespace Nibiru\Model;
use Nibiru\Adapter\MySQL\Db;
use Nibiru\Pdo;
class documentation extends Db
{
const TABLE = [
'table' => 'documentation',
'field' => [
'id' => 'id', 'title' => 'title', 'slug' => 'slug',
'content' => 'content', 'category' => 'category',
'version' => 'version',
],
];
public function __construct() { self::initTable(self::TABLE); }
public function getBySlug(string $slug): ?array {
return Pdo::fetchRowInArrayById(
self::TABLE['table'],
[self::TABLE['field']['slug'] => $slug]
) ?: null;
}
public function search(string $query): array {
$sql = 'SELECT * FROM ' . self::TABLE['table']
. ' WHERE title LIKE :q OR content LIKE :q ORDER BY title';
return Pdo::fetchAll($sql, [':q' => '%' . $query . '%']);
}
}

ジェネレーターが再度実行されると、database.overwrite = true の場合、このファイルは上書きされます。カスタムメソッドは子クラスに保持するか、最初の生成後には database.overwrite = false を設定してください。

パターン: 細かいモデル + モジュールプラグイン

Section titled “パターン: 細かいモデル + モジュールプラグイン”

複雑なドメイン(認証、課金、分析)では、デモンストレーションアプリケーションはクエリメソッドをモジュールプラグインに配置し、単なるモデルではなくします。プラグインがビジネスルールを持ち、モデルは単にテーブルへの型付けされたハンドルだけです:

application/module/users/
├── plugins/
│ └── user.php # User::isAuthorized(), User::loginForm(), …
└── traits/
└── userForm.php
``````php
namespace Nibiru\Module\Users\Plugin;
use Nibiru\Model\users;
class User {
private users $usersModel;
public function __construct() { $this->usersModel = new users(); }
public function isAuthorized(): bool {
return isset($_SESSION['auth']['user_id']);
}
public function findByLogin(string $login): ?array {
return \Nibiru\Pdo::fetchRow(
'SELECT * FROM users WHERE user_login = :login',
[':login' => $login]
) ?: null;
}
}

これにより、コントローラーは薄くなりますが($this->user->isAuthorized())、生成されたモデルは変更されません。

生成された Db アダプターはドライバーやせきにあります。MySQL から PostgreSQL に切り替える場合は、モデルを再生成して正しい基底クラスを継承するようにしてください。

  • MySQL / PDO → Nibiru\Adapter\MySQL\Db
  • PostgreSQL (libpq) → Nibiru\Adapter\PostgreSQL\Db
  • ODBC → Nibiru\Adapter\Odbc\Db

同じクエリヘルパーを使用していますが、内部で異なるアダプターを使用しています。

ジェネレーターをスキップする場合

Section titled “ジェネレーターをスキップする場合”

読み取り専用データベース、ベンダーのシステム、またはあなたがコントロールできないスキーマの場合:database = false を設定し、実際に使用する列に一致する最小限のモデルクラスを手書きして、チェックインしてください。