このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン 前のリビジョン 次のリビジョン | 前のリビジョン | ||
apricot:usage:ja:model [2020/08/03 11:46] tanaka [ORMの設定] |
apricot:usage:ja:model [2020/09/03 13:45] y2sunlight [Apricot モデルとサービス] |
||
---|---|---|---|
行 1: | 行 1: | ||
- | > 編集中 | + | ====== Apricot |
- | + | ||
- | ---- | + | |
- | + | ||
- | ====== Apricot データベースとモデル | + | |
--- // | --- // | ||
- | [[apricot: | + | [[apricot: |
目次 | 目次 | ||
+ | * [[apricot: | ||
* [[apricot: | * [[apricot: | ||
+ | * [[apricot: | ||
* [[apricot: | * [[apricot: | ||
* [[apricot: | * [[apricot: | ||
- | * Apricot データベースとモデル | + | * [[apricot: |
+ | * Apricot | ||
* [[apricot: | * [[apricot: | ||
* [[apricot: | * [[apricot: | ||
- | * [[apricot: | + | * [[apricot: |
+ | * [[apricot: | ||
+ | * [[apricot: | ||
* [[apricot: | * [[apricot: | ||
---- | ---- | ||
- | ===== ORMの設定 | + | モデルはデータベース上のテーブルと1対1に対応したクラスで、データベースからデータを取得または設定するためのメソッドを持っています。モデルのベースクラスは[[https:// |
- | ORマッパーには[[basic-library: | + | Apricotは比較的小規模なアプリケーション開発をターゲットにしているので、コントローラとモデルによってアプリケーションの作成が可能であると仮定しています。しかしながら、2つ以上のモデルを操作するような少し複雑なトランザクションが必要な場合は、それをサービスとして実装する必要があるかもしれません。現状のApricotではサービスの実装はアプリケーションの問題であるとする立場でなので、本章では、サービスの実装に関する若干のヒントを示すにだけに留めます。 |
- | ==== 設定ファイル ==== | + | \\ |
- | {{fa> | + | ===== Modelクラス |
- | <code php idiorm.setting.php> | + | |
- | <?php | + | モデルのベースクラスは、'' |
- | return | + | |
- | [ | + | <code> |
- | ' | + | / |
- | ' | + | |
- | ' | + | |
- | ' | + | |
- | ' | + | |
- | ], | + | |
- | ' | + | |
- | ' | + | |
- | ' | + | |
- | ' | + | |
- | ], | + | |
- | ' | + | |
- | [ | + | |
- | 'account' | + | |
- | ' | + | |
- | ' | + | |
- | ' | + | |
- | ], | + | |
- | ], | + | |
- | ], | + | |
- | ], | + | |
- | ]; | + | |
</ | </ | ||
- | * sqlite : 接続設定(apricotではSQLiteを使用します) | + | ModelクラスはほとんどのことをIdiormのORMクラスに頼っていますが、アプリケーションの共通的な処理を追加しています。Apricotのスケルトンでは、アプリケーションが使用する全てのテーブルで created_at、updated_at、version_no |
- | * sqlite.db_file --- データベースファイルのパス (既定値は var/ | + | |
- | * sqlite.connection_string --- 接続文字列 | + | |
- | * sqlite.caching --- キャッシングの有無 | + | |
- | * sqlite.logging --- ロギングの有無 | + | |
- | * initial_data : 初期データ (テーブルが空の時に自動設定されます) | + | * 新しくレコードが挿入される時、'' |
- | * {テーブル名} --- ここではユーザテーブル( user )を指定しています | + | * レコードが変更される時、'' |
- | * exec --- 実行したいSQLを記述します(複数指定可) | + | * '' |
- | * rows --- 行データを設定します(複数指定可) | + | |
- | 接続設定の詳細は以下を参照して下さい:\\ | + | これらの共通処理はアプリケーションに依存するところが大きく、必要に応じて、Modelクラスを変更して下さい。 |
- | https:// | + | |
\\ | \\ | ||
- | ==== 初期設定ファイル | + | ==== 命名規則 |
- | データベースの設定は初期設定ファイルで行います。 | + | クラス名とテーブル名の間の名前には以下の例のような命名規則があります。クラス名は Upper Camel (いわゆるPascalケース)、テーブル名はSnakeケースです。 |
- | {{fa> | + | ^クラス名^テーブル名^ |
- | <code php idiorm.setup.php> | + | |User|user| |
+ | |UserFriend|user_friend| | ||
+ | |||
+ | クラスのフィールド名とテーブルのカラム名は同じです。両者に命名規則はありません。 | ||
+ | |||
+ | \\ | ||
+ | |||
+ | ==== Modelのメソッド ==== | ||
+ | |||
+ | Modeクラスは以下のメソッドを持ちます。 | ||
+ | |||
+ | ^メソッド^機能^ | ||
+ | |tableName(): | ||
+ | |for_table(): | ||
+ | |findAll(): | ||
+ | |findOne(int $id): | ||
+ | |create(array $inputs=null): | ||
+ | |insert(array $inputs): | ||
+ | |update($id, | ||
+ | |delete($id): | ||
+ | |isSuccessful(): | ||
+ | |||
+ | === tableName() === | ||
+ | |||
+ | tableName() は命名規則に従ってクラス名からテーブル名をを取得するメソッドです。 | ||
+ | |||
+ | <code php> | ||
+ | $user = new User(); | ||
+ | $name = $user-> | ||
+ | </ | ||
+ | |||
+ | === forTable() === | ||
+ | |||
+ | ORMのforTable()をラップしたメソッドで、ORMオブジェクトを取得します。 | ||
+ | |||
+ | <code php> | ||
+ | $orm = $user-> | ||
+ | </ | ||
+ | |||
+ | === findAll() === | ||
+ | |||
+ | モデルの対象となるテーブルから全件を検索するメソッドです。このメソッドはORMの配列を返します。 | ||
+ | |||
+ | <code php> | ||
+ | $users = $user-> | ||
+ | foreach($users as $user) | ||
+ | { | ||
+ | $account = $user-> | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === findOne() === | ||
+ | |||
+ | モデルの対象となるテーブルから主キーによる検索を行うメソッドです。見つかった場合は ORM を、それ以外は false を返します。 | ||
+ | |||
+ | <code php> | ||
+ | $user = $user-> | ||
+ | if ($user !== false) | ||
+ | { | ||
+ | // Failure | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | $account = $user-> | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === create() === | ||
+ | |||
+ | 新しいORMオブジェクトを返します。 | ||
+ | |||
+ | <code php> | ||
+ | $new_user = $user-> | ||
+ | </ | ||
+ | |||
+ | 上の例では、新しいORMオブジェクトにはモデルのフィールドはありません。モデルに初期値を設定するには以下のようにします。 | ||
+ | |||
+ | <code php> | ||
+ | $new_user = $user-> | ||
+ | </ | ||
+ | |||
+ | === insert() === | ||
+ | |||
+ | 指定されたモデルデータをテーブルに挿入します。このメソッドはORMオブジェクトを返します。 | ||
+ | |||
+ | <code php> | ||
+ | $inputs = Input:: | ||
+ | |||
+ | $user = $user-> | ||
+ | $new_id = $user-> | ||
+ | </ | ||
+ | |||
+ | === update() === | ||
+ | |||
+ | 指定されたモデルデータでテーブルを更新します。このメソッドはORMオブジェクトを返します。レコードが存在しない時、'' | ||
+ | |||
+ | <code php> | ||
+ | $inputs = Input:: | ||
+ | |||
+ | try | ||
+ | { | ||
+ | $user-> | ||
+ | } | ||
+ | catch(ApplicationException $e) | ||
+ | { | ||
+ | // OptimissticLockException is also an ApplicationException. | ||
+ | // Do something. | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === delete() === | ||
+ | |||
+ | 指定された主キーのレコードをテーブルから削除します。このメソッドはORMオブジェクトを返します。レコードが存在しない時、ApplicationExceptionをスローします。 | ||
+ | |||
+ | <code php> | ||
+ | try | ||
+ | { | ||
+ | $user-> | ||
+ | } | ||
+ | catch(ApplicationException $e) | ||
+ | { | ||
+ | // Do something. | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === isSuccessful() === | ||
+ | |||
+ | 最新の更新結果をブーリアンで返します。対象は insert()、update()、delete()の各メソッドです。 | ||
+ | |||
+ | <code php> | ||
+ | $successful = $user-> | ||
+ | </ | ||
+ | |||
+ | \\ | ||
+ | |||
+ | ===== Modelの継承 ===== | ||
+ | |||
+ | 以下はもっとも簡単なModelの継承の例です。Modelを継承するだけで、Modelクラスのメソッドが利用でき、簡単なモデルなら直ぐにアクションの実装に取り掛かれます。 | ||
+ | |||
+ | {{fa> | ||
+ | <code php User.php> | ||
<?php | <?php | ||
- | // | + | namespace App\Models; |
- | // ORM(idirom)の初期設定 | + | use App\Foundation\Model; |
- | // | + | |
- | return function(): | + | /** |
+ | * User Model | ||
+ | */ | ||
+ | class User extends Model | ||
{ | { | ||
- | | + | } |
- | $db_file = config(' | + | </code> |
- | if (!file_exists($db_path=dirname($db_file))) | + | |
- | { | + | |
- | mkdir($db_path, | + | |
- | } | + | |
- | // DBファイルの存在確認 | + | 次の例は、Apticotのスケルトンで提供されているユーザモデルです。この例では、insert()とupdate()をオーバーロードして個別の処理を追加しています。 |
- | $new_db_file = !file_exists($db_file); | + | |
- | // データベース接続 | + | <code php User.php> |
- | ORM:: | + | <?php |
- | ' | + | namespace App\Models; |
- | ' | + | use App\Foundation\Model; |
- | ' | + | use ORM; |
- | ' | + | |
- | { | + | |
- | // SQL debug logging | + | |
- | \Core\Log:: | + | |
- | }, | + | |
- | ]); | + | |
- | | + | /** |
- | // テーブルの作成 | + | * User Model |
- | //------------------------------------------- | + | */ |
- | | + | class User extends Model |
+ | { | ||
+ | /** | ||
+ | * {@inheritDoc} | ||
+ | * @see \App\Foundation\Model:: | ||
+ | */ | ||
+ | | ||
{ | { | ||
- | $sql_text | + | |
- | if (!empty($sql_text)) | + | |
- | | + | |
- | foreach($sql_text as $sql) | + | |
- | { | + | |
- | ORM::get_db()-> | + | |
- | } | + | |
- | } | + | |
} | } | ||
- | // | + | /** |
- | // 初期ユーザの作成 | + | * {@inheritDoc} |
- | // | + | * @see \App\Foundation\Model:: |
- | | + | */ |
- | if (isset($initial_data)) | + | |
{ | { | ||
- | | + | |
+ | if(empty($inputs[' | ||
+ | |||
+ | if(array_key_exists(' | ||
{ | { | ||
- | | + | // Encrypts the entered password |
- | { | + | $inputs['password'] = password_hash($inputs['password' |
- | if (array_key_exists(' | + | |
- | { | + | |
- | | + | |
- | $exec = (array)$item['exec']; | + | |
- | foreach($exec as $sql) | + | |
- | { | + | |
- | ORM:: | + | |
- | } | + | |
- | } | + | |
- | if (array_key_exists(' | + | |
- | { | + | |
- | // 新しいレコードの作成 | + | |
- | $rows = (array)$item['rows']; | + | |
- | foreach($rows as $row) | + | |
- | { | + | |
- | $row = ORM:: | + | |
- | $row-> | + | |
- | $row-> | + | |
- | $row-> | + | |
- | } | + | |
- | } | + | |
- | } | + | |
} | } | ||
+ | |||
+ | return parent:: | ||
} | } | ||
+ | } | ||
+ | </ | ||
- | // SQLログ開始 | + | '' |
- | ORM:: | + | |
- | | + | \\ |
- | }; | + | |
+ | ===== サービス ===== | ||
+ | |||
+ | Apricotではサービスの実装に関する具体的で明確な指針を提供してはいませんが、その代わりに1つの例題を提供しています。この例題は、''/ | ||
+ | |||
+ | {{fa> | ||
+ | <code php SampleServices.php> | ||
+ | <?php | ||
+ | namespace App\Services; | ||
+ | |||
+ | /** | ||
+ | * Sample Service | ||
+ | */ | ||
+ | class SampleService | ||
+ | { | ||
+ | /** | ||
+ | * The number of users | ||
+ | * @var int | ||
+ | */ | ||
+ | private $count = 0; | ||
+ | |||
+ | /** | ||
+ | * Creates a sample service. | ||
+ | */ | ||
+ | public function __construct(\App\Models\User $user) | ||
+ | { | ||
+ | $this-> | ||
+ | | ||
+ | |||
+ | | ||
+ | * Get the number of users | ||
+ | */ | ||
+ | public function getUserCount() | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | } | ||
</ | </ | ||
- | 初期設定ファイルでは以下の事をおこないます: | + | サービスの構造は[[apricot: |
- | * データベースの保存フォルダが存在しない場合は作成します | + | これらの問題を解決する為に、Apricotのコアが使用している [[https:// |
- | * データベースへの接続 | + | |
- | * テーブルの作成 (新しくDBを作った時) | + | |
- | * 初期ユーザの作成 (ユーザテーブルが空の時) | + | |
- | * SQLログの開始 (logging設定がtrueの場合) | + | |
- | \\ | + | Apricotでは League/ |
+ | === Auto Wiring === | ||
- | ===== データベースの構築 ===== | + | Auto Wiring とは、コンストラクター引数の型ヒントを調べることにより、オブジェクトとそのすべての依存関係を再帰的に自動的に解決する機能です。これによってコントローラーにモデルやサービスのコンストラクタインジェクションが実現できます。詳しくは「[[apricot: |
- | >TODO | + | |
- | \\ | + | === サービスプロバイダー === |
- | ===== モデル ===== | + | サービスプロバイダーを利用して、サービスをシングルトンとしてアプリケーションに登録することができます。詳しくは、「[[apricot: |
- | >TODO | + | |
\\ | \\ | ||
- |