このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン 前のリビジョン 次のリビジョン | 前のリビジョン | ||
|
apricot:app:db-model [2020/05/11 13:19] y2sunlight [テスト実行] |
apricot:app:db-model [2020/05/23 14:58] (現在) y2sunlight [モデルクラス] |
||
|---|---|---|---|
| 行 1: | 行 1: | ||
| - | > | ||
| - | |||
| - | ----- | ||
| - | |||
| ====== Apricot データベースとモデル ====== | ====== Apricot データベースとモデル ====== | ||
| --- // | --- // | ||
| 行 18: | 行 14: | ||
| * Apricot データベースとモデル | * Apricot データベースとモデル | ||
| * [[apricot: | * [[apricot: | ||
| - | * [[apricot: | + | * [[apricot: |
| * [[apricot: | * [[apricot: | ||
| * [[apricot: | * [[apricot: | ||
| - | * [[apricot: | + | * [[apricot: |
| \\ | \\ | ||
| 行 256: | 行 252: | ||
| \\ | \\ | ||
| - | ==== テスト実行 ==== | + | ===== テスト実行 |
| - | データベースファイル(apricot.sqlite)を作ってみましょう。 | + | データベースファイル(apricot.sqlite)を作ってみましょう。ブラウザ上で以下のURLにアクセス、Apricotのホーム画面を表示して下さい。 |
| - | + | ||
| - | ブラウザ上で以下のURLにアクセス、Apricotのホーム画面を表示して下さい。 | + | |
| < | < | ||
| 行 266: | 行 260: | ||
| </ | </ | ||
| - | まだユーザ登録機能を実装していないので、ユーザテーブルの内容を見る事はできませんが、以下の場所にデータベースファイルが作成されていることを確認して下さい。 | + | まだユーザ登録機能を実装していないので、アプリからユーザテーブルの内容を見る事はできませんが、以下の場所にデータベースファイルが作成されていることを確認して下さい。 |
| {{fa> | {{fa> | ||
| - | Sqlite の内容を確認するには、[[tools: | + | Sqliteデータベースの内容を確認するには、[[tools: |
| - | + | ||
| - | Eclipseからデータベースの内容を参照したい場合は、DBeaverプラグイン | + | |
| === DBeaverプラグインのインストール方法 === | === DBeaverプラグインのインストール方法 === | ||
| 行 280: | 行 272: | ||
| * [一般用ツール][マーケットプレース・クライアント]をインストール | * [一般用ツール][マーケットプレース・クライアント]をインストール | ||
| * Eclipseの再起動 | * Eclipseの再起動 | ||
| - | * メニューから[Eclipseマーケットプレース]を選択 | + | * メニューから[ヘルプ][Eclipseマーケットプレース]を選択 |
| * [DBeaver]を検索してインストール | * [DBeaver]を検索してインストール | ||
| * Eclipseの再起動 | * Eclipseの再起動 | ||
| 行 291: | 行 283: | ||
| * データベースブラウザから | * データベースブラウザから | ||
| * SQLite - apricot.sqlite をクリック | * SQLite - apricot.sqlite をクリック | ||
| - | * SQLiteドライバーをダウンロード(初回のみ) | + | * SQLiteドライバー(jdbc)をダウンロード(初回のみ) |
| * [テーブル][user]をクリック | * [テーブル][user]をクリック | ||
| + | |||
| + | [{{: | ||
| + | |||
| \\ | \\ | ||
| ===== モデルクラス ===== | ===== モデルクラス ===== | ||
| - | >TODO | + | |
| + | ORマッパーが使えるようになったので、モデルのベースクラス( Model )を作ります。Modelクラスは必ず継承して使い、以下のメソッドを持ちます。詳しくはソースコードを参照して下さい。 | ||
| + | |||
| + | ^メソッド名^機能^ | ||
| + | |tableName()\\ : | ||
| + | |for_table()\\ : | ||
| + | |findAll()\\ : | ||
| + | |findOne\\ (int $id): | ||
| + | |create\\ (array $inputs=null): | ||
| + | |insert\\ (array $inputs): | ||
| + | |update\\ ($id, array $inputs): | ||
| + | |delete\\ ($id): | ||
| + | |isSuccess()\\ : | ||
| + | |||
| + | ソースコードを以下に示します。 | ||
| + | |||
| + | {{fa>folder-open-o}} ** / | ||
| + | <code php Model.php> | ||
| + | <?php | ||
| + | namespace App\Foundation; | ||
| + | |||
| + | use ORM; | ||
| + | use App\Exceptions\OptimissticLockException; | ||
| + | use App\Exceptions\ApplicationException; | ||
| + | |||
| + | /** | ||
| + | * モデル | ||
| + | */ | ||
| + | class Model | ||
| + | { | ||
| + | /** | ||
| + | * 最新の更新結果(insert/ | ||
| + | * @var bool | ||
| + | */ | ||
| + | private $success = false; | ||
| + | |||
| + | /** | ||
| + | * テーブル名の取得 | ||
| + | * @return string | ||
| + | */ | ||
| + | public function tableName(): | ||
| + | { | ||
| + | return snake_case(get_short_class_name($this)); | ||
| + | } | ||
| + | |||
| + | /** | ||
| + | * テーブルの取得 | ||
| + | * @return \ORM | ||
| + | */ | ||
| + | public function for_table(): | ||
| + | { | ||
| + | return ORM:: | ||
| + | } | ||
| + | |||
| + | /** | ||
| + | * 全件検索 | ||
| + | * @return array|\IdiormResultSet | ||
| + | */ | ||
| + | public function findAll() | ||
| + | { | ||
| + | return $this-> | ||
| + | } | ||
| + | |||
| + | /** | ||
| + | * 主キー検索 | ||
| + | * @param int $id | ||
| + | * @return \ORM|false returna single instance of the ORM class, or false if norows were returned. | ||
| + | */ | ||
| + | public function findOne(int $id) | ||
| + | { | ||
| + | return $this-> | ||
| + | } | ||
| + | |||
| + | /** | ||
| + | * 新規作成 | ||
| + | * @return \ORM | ||
| + | */ | ||
| + | public function create(array $inputs=null): | ||
| + | { | ||
| + | return $this-> | ||
| + | } | ||
| + | |||
| + | /** | ||
| + | * 新規保存 | ||
| + | * @param array $inputs | ||
| + | * @return \ORM | ||
| + | */ | ||
| + | public function insert(array $inputs): | ||
| + | { | ||
| + | $row = $this-> | ||
| + | $row-> | ||
| + | $row-> | ||
| + | $this-> | ||
| + | return $row; | ||
| + | } | ||
| + | |||
| + | /** | ||
| + | * データ更新 | ||
| + | * @param mixed $id | ||
| + | * @param array $inputs | ||
| + | * @return \ORM | ||
| + | */ | ||
| + | public function update($id, array $inputs): | ||
| + | { | ||
| + | // ApricotではSQLite3.0.8以上の使用を前提としており、トランザクション分離レベルはデフォルト値がDEFERREDです。 | ||
| + | // DEFERRED は最初の読み取り時に共有ロックが掛かります(SQLiteのロックはデータベースロックです)。 | ||
| + | // 従って、version_no読み取り後はトランザクション終了まで他の更新は発生しません。 | ||
| + | // NOTE: 他のデータベースの場合は、ここで行ロックを取得してレコードの検索を行います(select for update) | ||
| + | $row = $this-> | ||
| + | if ($row===false) | ||
| + | { | ||
| + | throw new ApplicationException(__(' | ||
| + | } | ||
| + | |||
| + | // 楽観的ロックの検証 | ||
| + | if ($row-> | ||
| + | { | ||
| + | throw new OptimissticLockException(); | ||
| + | } | ||
| + | |||
| + | // データ更新 | ||
| + | $row-> | ||
| + | $row-> | ||
| + | $row-> | ||
| + | $this-> | ||
| + | return $row; | ||
| + | } | ||
| + | |||
| + | /** | ||
| + | * データ削除 | ||
| + | * @param mixed $id | ||
| + | * @return \ORM | ||
| + | */ | ||
| + | public function delete($id): | ||
| + | { | ||
| + | $row = $this-> | ||
| + | if ($row===false) | ||
| + | { | ||
| + | throw new ApplicationException(__(' | ||
| + | } | ||
| + | $this-> | ||
| + | return $row; | ||
| + | } | ||
| + | |||
| + | /** | ||
| + | * 最新の更新結果の取得(insert/ | ||
| + | * @return bool | ||
| + | */ | ||
| + | public function isSuccess(): | ||
| + | { | ||
| + | return $this-> | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ORMオブジェクトについては、以下のIdiormのドキュメントを参照して下さい: | ||
| + | |||
| + | * https:// | ||
| \\ | \\ | ||