Ground Sunlight

Windowsで作る - PHPプログラミングの開発環境

ユーザ用ツール

サイト用ツール


apricot:usage:ja:model

差分

このページの2つのバージョン間の差分を表示します。

この比較画面にリンクする

次のリビジョン
前のリビジョン
apricot:usage:ja:model [2020/07/29 13:27]
tanaka 作成
apricot:usage:ja:model [2020/09/03 13:45] (現在)
y2sunlight [Apricot モデルとサービス]
行 1: 行 1:
-> 編集中 +====== Apricot ルとサス ======
- +
----- +
- +
-====== Apricot データベーとモデル ======+
  --- //[[http://www.y2sunlight.com|y2sunlight]] 2020-07-29//  --- //[[http://www.y2sunlight.com|y2sunlight]] 2020-07-29//
  
-[[apricot:usage:ja|Apricotの使用法 に戻る]]+[[apricot:usage:ja|Apricot ドキュメント に戻る]]
  
 目次 目次
  
 +  * [[apricot:usage:ja:features|Apricot 特徴と概要]]
   * [[apricot:usage:ja:config|Apricot 配置と構成]]   * [[apricot:usage:ja:config|Apricot 配置と構成]]
 +  * [[apricot:usage:ja:errors-logging|Apricot ログとエラー処理]]
   * [[apricot:usage:ja:http|Apricot リクエストとレスポンス]]   * [[apricot:usage:ja:http|Apricot リクエストとレスポンス]]
   * [[apricot:usage:ja:frontend|Apricot フロントエンド]]   * [[apricot:usage:ja:frontend|Apricot フロントエンド]]
-  * Apricot データベースモデル+  * [[apricot:usage:ja:database|Apricot データベース]] 
 +  * Apricot モデルとサービス
   * [[apricot:usage:ja:middleware|Apricot ミドルウェア]]   * [[apricot:usage:ja:middleware|Apricot ミドルウェア]]
   * [[apricot:usage:ja:controller|Apricot コントローラ]]   * [[apricot:usage:ja:controller|Apricot コントローラ]]
-  * [[apricot:usage:ja:errors-logging|Apricot ログとエラ処理]]+  * [[apricot:usage:ja:validation|Apricot バリデーション]] 
 +  * [[apricot:usage:ja:provider|Apricot サービスプバイダー]] 
 +  * [[apricot:usage:ja:authentication|Apricot ユザ認証]]
   * [[apricot:usage:ja:utility|Apricot ユーティリティ]]   * [[apricot:usage:ja:utility|Apricot ユーティリティ]]
  
 ---- ----
  
-===== データベースの用 ===== +モデルはデータベーステーブルと1対1に対応したクラスで、データベースからデータを取得または設定するためのメソッドを持っています。モデルのベースクラスは[[https://github.com/j4mie/idiorm|Idiorm]]を使して作成しています。 
->TODO+ 
 +Apricotは比較的小規模なアプリケーション開発をターゲットにしているので、コントローラとモデルによってアプリケーションの作成が可能であると仮定しています。しかしながら、2つ以上のモデルを操作するような少し複雑なトランザクションが必要な場合は、それをサービスとして実装する必要があるかもしれません。現状のApricotではサービスの実装はアプリケーションの問題であるとする立場でなので、本章では、サービスの実装に関する若干のヒントを示すにだけに留めます。
  
 \\ \\
  
-===== モデル ===== +===== Modelクラス ===== 
->TODO+ 
 +モデルのベースクラスは、''App\Foundation\Model'' です。全てのモデルクラスはこのクラスから継承して作成します。Modelから継承したクラスは以下の場所に配置することを推奨していますが、これは必須ではありません。適宜アプリケーションのルールで変更して下さい。 
 + 
 +<code> 
 +/your-project/app/Models 
 +</code> 
 + 
 +ModelクラスはほとんどのことをIdiormのORMクラスに頼っていますが、アプリケーションの共通的な処理を追加しています。Apricotのスケルトンでは、アプリケーションが使用する全てのテーブルで created_at、updated_at、version_no の3つカラムが存在します。 
 + 
 +  * 新しくレコードが挿入される時、''created_at''と''updated_at'' が 設定されます。 
 +  * レコードが変更される時、''created_at''と''version_no'' が 設定されます。 
 +  * ''version_no'' はレコードのバージョンを表し、楽観的ロックで使用されます。 
 + 
 +これらの共通処理はアプリケーションに依存するところが大きく、必要に応じて、Modelクラスを変更して下さい。
  
 \\ \\
  
-===== サービスプロバイダー ===== +==== 命名規則 ==== 
->TODO+ 
 +クラス名とテーブル名の間の名前には以下の例のような命名規則があります。クラス名は Upper Camel (いわゆるPascalケース)、テーブル名はSnakeケースです。 
 + 
 +^クラス名^テーブル名^ 
 +|User|user| 
 +|UserFriend|user_friend|  
 + 
 +クラスのフィールド名とテーブルのカラム名は同じです。両者に命名規則はありません。
  
 \\ \\
  
 +==== Modelのメソッド ====
 +
 +Modeクラスは以下のメソッドを持ちます。
 +
 +^メソッド^機能^
 +|tableName():string|テーブル名の取得|
 +|for_table():ORM|ORMオブジェクトの取得|
 +|findAll():array|全件検索(ORMの配列を返します)|
 +|findOne(int $id):mixed|主キー検索(ORMまたはfalseを返します)|
 +|create(array $inputs=null):ORM|モデルの新規作成|
 +|insert(array $inputs):ORM|レコードの挿入|
 +|update($id, array $inputs):ORM|レコードの更新|
 +|delete($id):ORM|レコードの削除|
 +|isSuccessful():bool|最新の更新結果の成否の取得|
 +
 +=== tableName() ===
 +
 +tableName() は命名規則に従ってクラス名からテーブル名をを取得するメソッドです。
 +
 +<code php>
 +$user = new User();
 +$name = $user->tableName(); // return 'user'
 +</code>
 +
 +=== forTable() ===
 +
 +ORMのforTable()をラップしたメソッドで、ORMオブジェクトを取得します。
 +
 +<code php>
 +$orm = $user->forTable();
 +</code>
 +
 +=== findAll() ===
 +
 +モデルの対象となるテーブルから全件を検索するメソッドです。このメソッドはORMの配列を返します。
 +
 +<code php>
 +$users = $user->findAll();
 +foreach($users as $user)
 +{
 +    $account = $user->account;
 +}
 +</code>
 +
 +=== findOne() ===
 +
 +モデルの対象となるテーブルから主キーによる検索を行うメソッドです。見つかった場合は ORM を、それ以外は false を返します。
 +
 +<code php>
 +$user = $user->findOne($id);
 +if ($user !== false)
 +{
 +    // Failure
 +}
 +else
 +{
 +    $account = $user->account;
 +}
 +</code>
 +
 +=== create() ===
 +
 +新しいORMオブジェクトを返します。
 +
 +<code php>
 +$new_user = $user->create();
 +</code>
 +
 +上の例では、新しいORMオブジェクトにはモデルのフィールドはありません。モデルに初期値を設定するには以下のようにします。
 +
 +<code php>
 +$new_user = $user->create(['account'=>'new_account']);
 +</code>
 +
 +=== insert() ===
 +
 +指定されたモデルデータをテーブルに挿入します。このメソッドはORMオブジェクトを返します。
 +
 +<code php>
 +$inputs = Input::all();
 +
 +$user = $user->insert($inputs);
 +$new_id = $user->id;
 +</code>
 +
 +=== update() ===
 +
 +指定されたモデルデータでテーブルを更新します。このメソッドはORMオブジェクトを返します。レコードが存在しない時、''ApplicationException'' がスローされ、また、楽観的ロック例外を検知した時は、''OptimissticLockException'' がスローされます。これらの例外については「[[apricot:usage:ja:errors-logging#アプリの例外クラス]]」も参照して下さい。
 +
 +<code php>
 +$inputs = Input::all();
 +
 +try
 +{
 +    $user->update($inputs['id'], $inputs);
 +}
 +catch(ApplicationException $e)
 +{
 +    // OptimissticLockException is also an ApplicationException.
 +    // Do something.
 +}
 +</code>
 +
 +=== delete() ===
 +
 +指定された主キーのレコードをテーブルから削除します。このメソッドはORMオブジェクトを返します。レコードが存在しない時、ApplicationExceptionをスローします。
 +
 +<code php>
 +try
 +{
 +    $user->delete($id);
 +}
 +catch(ApplicationException $e)
 +{
 +    // Do something.
 +}
 +</code>
 +
 +=== isSuccessful() ===
 +
 +最新の更新結果をブーリアンで返します。対象は insert()、update()、delete()の各メソッドです。
 +
 +<code php>
 +$successful = $user->isSuccessful();
 +</code>
 +
 +\\
 +
 +===== Modelの継承 =====
 +
 +以下はもっとも簡単なModelの継承の例です。Modelを継承するだけで、Modelクラスのメソッドが利用でき、簡単なモデルなら直ぐにアクションの実装に取り掛かれます。
 +
 +{{fa>folder-open-o}} ** /your-project/app/Models **
 +<code php User.php>
 +<?php
 +namespace App\Models;
 +use App\Foundation\Model;
 +
 +/**
 + * User Model
 + */
 +class User extends Model
 +{
 +}
 +</code>
 +
 +次の例は、Apticotのスケルトンで提供されているユーザモデルです。この例では、insert()とupdate()をオーバーロードして個別の処理を追加しています。
 +
 +<code php User.php>
 +<?php
 +namespace App\Models;
 +use App\Foundation\Model;
 +use ORM;
 +
 +/**
 + * User Model
 + */
 +class User extends Model
 +{
 +    /**
 +     * {@inheritDoc}
 +     * @see \App\Foundation\Model::insert()
 +     */
 +    public function insert(array $inputs):ORM
 +    {
 +        // Encrypt the password that is required for new registration.
 +        $inputs['password'] = password_hash($inputs['password'], PASSWORD_DEFAULT);
 +
 +        return parent::insert($inputs);
 +    }
 +
 +    /**
 +     * {@inheritDoc}
 +     * @see \App\Foundation\Model::update()
 +     */
 +    public function update($id, array $inputs):ORM
 +    {
 +        // Updates a password only if entered
 +        if(empty($inputs['password'])) unset($inputs['password']);
 +
 +        if(array_key_exists('password', $inputs))
 +        {
 +            // Encrypts the entered password
 +            $inputs['password'] = password_hash($inputs['password'], PASSWORD_DEFAULT);
 +        }
 +
 +        return parent::update($id, $inputs);
 +    }
 +}
 +</code>
 +
 +''insert()'' では、パスワードを暗号化して保存しています。また、''update()'' では、パスワードが入力された場合のみ暗号化し、そうでない場合は、入力変数からてパスワードを除外しています。このように、個別のモデルでは必要に応じてメソッドをオーバーライドしたり追加したりして下さい。
 +
 +\\
 +
 +===== サービス =====
 +
 +Apricotではサービスの実装に関する具体的で明確な指針を提供してはいませんが、その代わりに1つの例題を提供しています。この例題は、''/your-project/app/Services'' に配置されています。この配置場所は規則ではありませんので、必要に応じて変更して下さい。
 +
 +{{fa>folder-open-o}} ** /your-project/app/Services **
 +<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->count = count($user->findAll());
 +    }
 +
 +    /**
 +     * Get the number of users
 +     */
 +    public function getUserCount()
 +    {
 +        return $this->count;
 +    }
 +}
 +</code>
 +
 +サービスの構造は[[apricot:usage:ja:controller#コントローラ]]に似ています。クラス間の依存性を疎にする為に、コンストラクターでモデルや他のオブジェクトを受け取る場合、コンストラクタインジェクションが必要になるかもしれません。また、サービスがコントローラ、ミドルウェア、テンプレートなどの様々な場所から呼び出される場合は、シングルトンが要求されるかもしれません。
 +
 +これらの問題を解決する為に、Apricotのコアが使用している [[https://github.com/thephpleague/container|League/Container]] が利用できます。これはサービスに関する強力なツールになるはずです。
 +
 +Apricotでは League/Container を利用した以下の機能が使用できます。
 +
 +=== Auto Wiring ===
 +
 +Auto Wiring とは、コンストラクター引数の型ヒントを調べることにより、オブジェクトとそのすべての依存関係を再帰的に自動的に解決する機能です。これによってコントローラーにモデルやサービスのコンストラクタインジェクションが実現できます。詳しくは「[[apricot:usage:ja:controller#auto_wiring]]」を参照して下さい。
 +
 +=== サービスプロバイダー ===
 +
 +サービスプロバイダーを利用して、サービスをシングルトンとしてアプリケーションに登録することができます。詳しくは、「[[apricot:usage:ja:provider|League/Container]]」を参照して下さい。
 +
 +\\
apricot/usage/ja/model.1595996850.txt.gz · 最終更新: 2020/07/29 13:27 by tanaka