Ground Sunlight

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

ユーザ用ツール

サイト用ツール


apricot:usage:ja:model

差分

このページの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 データベーとモデル ======+
  --- //[[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 ユーティリティ]]
  
 ---- ----
  
-===== ORMの設定 =====+モデルはデータベース上テーブルと1対1に対応したクラスで、データベースからデータを取得または設定するためのメソッドを持っています。モデルのベースクラスは[[https://github.com/j4mie/idiorm|Idiorm]]を使用して作成しています。
  
-ORマーには[[basic-library:idiorm:1.5|Idiorm]]を使用します。Idiormは元々シングルトンとして実装してあるのでまま使えま。使い方やメソッドについてIdiorm[[https://idiorm.readthedocs.io/en/latest/|マニュアル]]参照して下さい+Apricotは比較的小規模なアプリケーション開発をターゲトにしているので、コントロラとモデルよってアプリケーションの作成が可能であると仮定ています。しかしながら、2つ以上のモデを操作するような少し複雑なザクションが必要な場合は、それをサービスとして実装する必要があるかもしれません。現状Apricotはサービス実装はアプリケーションの問題であるとる立場でなので、本章で、サービス実装に関する若干のヒント示すにだけに留めます
  
-==== 設定ファイル ====+\\
  
-{{fa>folder-open-o}} ** /apricot/config/setting ** +===== Modelクラス ===== 
-<code php idiorm.setting.php> + 
-<?php +モデルのベースクラスは、''App\Foundation\Model'' です。全てのモデルクラスはこのクラスから継承して作成します。Modelから継承したクラスは以下の場所に配置することを推奨していますが、これは必須ではありません。適宜アプリケーションのルールで変更して下さい。 
-return + 
-+<code
-    'sqlite' => [ +/your-project/app/Models
-        'db_file' => var_dir('db/apricot.sqlite'), +
-        'connection_string' => 'sqlite:'.var_dir('db/apricot.sqlite'), +
-        'caching' => true, +
-        'logging' => true, +
-    ], +
-    'initial_data' => [ +
-        'user'=> [ +
-            'exec' =>[ +
-                'delete from sqlite_sequence where name=\'user\'', +
-            ], +
-            'rows' => [ +
-                [ +
-                    'account=>'root', +
-                    'password' =>password_hash('', PASSWORD_DEFAULT), +
-                    'email' =>'root@sample.com', +
-                    'note' =>'Initial User', +
-                ], +
-            ], +
-        ], +
-    ], +
-];+
 </code> </code>
  
-  * sqlite : 接続設定(apricotでSQLite使用します+ModelクラスほとんどのことIdiormのORMクラスに頼っていますが、アプリケションの共通的な処理を追加しています。Apricotのスケルトンで、アプリケーが使用する全てテーブルで created_at、updated_at、version_no 3つカラムが存在します。
-    * sqlite.db_file --- デタベースファイルス (既定値は var/db/apricot.sqlite'+
-    * sqlite.connection_string --- 接続文字列 +
-    * sqlite.caching --- キャッシン有無 +
-    * sqlite.logging --- ロギング有無+
  
-  * initial_data : 初期デタ (テーブル空のに自動設定されます) +  * 新しくレコ挿入される、''created_at''と''updated_at'' が 設定されます 
-    {テブル名} --- ここではユーザテーブル( user )を指しています +  レコドが変更される時、''created_at''と''version_no'' が 設されます 
-      exec --- 実行したいSQLを記述します(複数指定可) +  ''version_no'' はレコドのバージョン、楽観的ロックで使用されます
-      * rows --- 行デ設定します(複数指定可)+
  
-接続設定詳細以下参照して下さい:\\  +これら共通処理アプリケーションに依存するところが大きく、必要に応じて、Modelクラス変更して下さい
-https://idiorm.readthedocs.io/en/latest/configuration.html#id1+
  
 \\ \\
  
-==== 初期設定ファイル ====+==== 命名規則 ====
  
-データベースの設定初期設定ファイルで行います。+クラ名とテーブル名間の名前に以下の例のような命名規則があります。クラス名は Upper Camel (いわゆるPascalケース)、テーブ名はSnakeケースです。
  
-{{fa>folder-open-o}} ** /apricot/config/setup ** +^クラス名^テーブル名^ 
-<code php idiorm.setup.php>+|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 <?php
-//------------------------------------------------------------------- +namespace App\Models; 
-// ORM(idirom)の初期設定 +use App\Foundation\Model; 
-//------------------------------------------------------------------- + 
-return function():bool+/** 
 + * User Model 
 + *
 +class User extends Model
 { {
-    // データベースファイルの準備 +
-    $db_file = config('idiorm.sqlite.db_file'); +</code>
-    if (!file_exists($db_path=dirname($db_file))) +
-    { +
-        mkdir($db_path,null,true); +
-    }+
  
-    // DBファイルの存在確認 +次の例は、Apticotのスケトンで提供されているユーザモデルです。こ例では、insert()とupdate()をオーバーロードして個別の処理を追加しています。
-    $new_db_file = !file_exists($db_file);+
  
-    // データベース接続 +<code php User.php
-    ORM::configure([ +<?php 
-        'connection_string' => config('idiorm.sqlite.connection_string'), +namespace App\Models; 
-        'caching' =config('idiorm.sqlite.caching',false), +use App\Foundation\Model
-        'logging' => false, +use ORM;
-        'logger' => function($log_string, $query_time) +
-        { +
-            // SQL debug logging +
-            \Core\Log::info("SQL",[$log_string])+
-        }, +
-    ]);+
  
-    //------------------------------------------- +/** 
-    // テーブルの作成 (新しくDBを作った時+ * User Model 
-    //------------------------------------------- + */ 
-    if ($new_db_file)+class User extends Model 
 +{ 
 +    /** 
 +     * {@inheritDoc} 
 +     * @see \App\Foundation\Model::insert() 
 +     *
 +    public function insert(array $inputs):ORM
     {     {
-        $sql_text file_get_sql(assets_dir('sql/create.sql')); +        // Encrypt the password that is required for new registration. 
-        if (!empty($sql_text)) +        $inputs['password'password_hash($inputs['password'], PASSWORD_DEFAULT); 
-        + 
-            foreach($sql_text as $sql) +        return parent::insert($inputs);
-            { +
-                ORM::get_db()->exec($sql); +
-            } +
-        }+
     }     }
  
-    //------------------------------------------- +    /** 
-    // 初期ユーザの作成 (ユーザテーブルが空の時+     * {@inheritDoc} 
-    //------------------------------------------- +     * @see \App\Foundation\Model::update() 
-    $initial_data = config('idiorm.initial_data'); +     *
-    if (isset($initial_data))+    public function update($id, array $inputs):ORM
     {     {
-        foreach($initial_data as $key=>$item)+        // Updates a password only if entered 
 +        if(empty($inputs['password'])) unset($inputs['password']); 
 + 
 +        if(array_key_exists('password', $inputs))
         {         {
-            if(ORM::for_table($key)->find_one()===false) +            // Encrypts the entered password 
-            { +            $inputs['password'] = password_hash($inputs['password'], PASSWORD_DEFAULT);
-                if (array_key_exists('exec', $item)) +
-                { +
-                    // SQLの実行 +
-                    $exec = (array)$item['exec']+
-                    foreach($exec as $sql) +
-                    { +
-                        ORM::get_db()->exec($sql); +
-                    } +
-                } +
-                if (array_key_exists('rows', $item)) +
-                { +
-                    // 新しいレコードの作成 +
-                    $rows = (array)$item['rows']+
-                    foreach($rows as $row) +
-                    { +
-                        $row = ORM::for_table($key)->create($row); +
-                        $row->set_expr('created_at'"datetime('now')"); +
-                        $row->set_expr('updated_at', "datetime('now')"); +
-                        $row->save(); +
-                    } +
-                } +
-            }+
         }         }
 +
 +        return parent::update($id, $inputs);
     }     }
 +}
 +</code>
  
-    // SQLログ開始 +''insert()'' では、パスワードを暗号化して保存しています。また、''update()'' では、パスワードが入力された場合のみ暗号化し、そうでない場合は、入力変数からてパスワードを除外しています。このように、個別のモデルでは必要に応じてメソッドをオーバーライドしたり追加したりして下さい。 
-    ORM::configure('logging, config('idiorm.sqlite.logging',false)); + 
-    return true; // Must return true on success +\\ 
-};+ 
 +===== サービス ===== 
 + 
 +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> </code>
  
-初期設定ファイルで以下おこす:+サービスの構造[[apricot:usage:ja:controller#コントローラ]]に似ています。クラス間依存性疎にする為に、コンストラクターでモデルや他のオブジェクトを受け取る場合、コンストラクタインジェクションが必要にるかもしれせん。また、サービスがコントローラ、ミドルウェア、テンプレートなどの様々な場所から呼び出される場合は、シングルトンが要求されるかもしれません。
  
-  * データベース保存フォルダ存在場合は作成します +これら問題を解決する為に、Apricotのコア使用る [[https://github.com/thephpleague/container|League/Container]] が利用できます。これはサに関する強力なツールになるはずです。
-  * データベースへの接続 +
-  * テの作成 (新しくDBを作った時) +
-  * 初期ユーザの作成 (ユーザテーブルが空の時) +
-  * SQLログの開始 (logging設定がtrueの場合)+
  
-\\+Apricotでは League/Container を利用した以下の機能が使用できます。
  
 +=== Auto Wiring ===
  
-===== デーースの構築 ===== +Auto Wiring とは、コンストラクター引数の型ヒントを調べることにより、オブジェクトとそのすべての依存関係を再帰的に自動的に解決する機能です。これによってコントローラーにモデルやサービスのコンストラクタインジェクションが実現できます。詳しくは「[[apricot:usage:ja:controller#auto_wiring]]」を参照して下さい。
->TODO+
  
-\\+=== サービスプロバイダー ===
  
-===== モデル ===== +サービスプロバイダーを利用して、サービスをシングトンとしてアプリケーションに登録することができます。詳しくは、「[[apricot:usage:ja:provider|League/Container]]」を参照して下さい。
->TODO+
  
 \\ \\
- 
apricot/usage/ja/model.txt · 最終更新: 2020/09/03 13:45 by y2sunlight