モデルについて
Modelはアプリケーション(プロジェクト)のデータベース連携機能を集中的に集めたLaravelの要素です。
Modelを構成するのはマイグレーションというデータベースの構成管理ファイルと
モデルというLaravelで準備されているModelクラスを継承して個別にデータベースを操作する機能を集約させたファイルです。
いずれもPHPで記述され、クラスとしてアプリケーション(プロジェクト)のなかで管理されます。
アプリケーション(プロジェクト)の全体設定
まず、Model関連のファイルを生成する前にLaravelとデータベースとの連携を行う全体設定を行います。
アプリケーション(プロジェクト)自体の全体設定はプロジェクトルートディレクトリ(ここではhttpd>DMENAフォルダ)直下の.envファイルで行います。
ここでデータベース関連以外の全体設定もしてしまいます。
まず.env をひらきます。
デフォルトではAPP_NAME=laravel になっているので、これをDMENAに変更します。
次にデータベース関連の全体設定をします。
データベースのプロファイルを確認するためにXampp Controll PanelでMySQLを立ち上げて、表示される各プロファイルを確認します。
まず重要なのがPort(s) です。大体XamppでMySQLを動かすと3306番が付与されるようです。.env でもデフォルトで3306番が記載されています。
そしてデータベース名。
これはこのアプリ用に作成したMySQL用のデータベース名を記載します。
データベースはControll Panelの「Admin」ボタンを押すと立ち上がるPHP MyAdminという管理ツールから作成できます。
この画面ではこのアプリケーションようにdmenaというデータベースがすでに作成されています。
以上を確認して.envに戻ります。そして確認した情報をデータベースプロファイルに反映させます。
DB_PORT=3306
DB_NAME=dmena
DB_USERNAME=root
DB_PASSWORD= ※Xamppではデフォルトブランクになっていますから.envもブランクで大丈夫です。
しかし基本は何らかの設定をすべき箇所です。
次に文字コードの設定を行います。
これは.envではなくプロジェクトルートディレクトリ以下 APP>Providers>AppServiceProviders.php ファイルを修正します。
まず、上部のクラス導入部に
use Illuminate\Support\Facades\Schema; -※\はバックスラッシュ
を追記して
boot() メソッドの中に
Schema::defaultStringLength(191);
を追記します。
AppServiceProviders.phpを保存します。
最後にタイムゾーンの設定を行います。
タイムゾーンはプロジェクトルートディレクトリ以下 config>app.php ファイルを修正します。
このtimezone とlocale を修正します。
'timezone'=>'Asia/Tokyo',
'locale'=>'ja',
.envを保存します。
マイグレーションの作成
マイグレーションは冒頭に触れたようにデータベースの構造管理を行います。
例えばデータベースシステムにはMysql、SQLiteやpgsqlなど様々な種類があります。
またそれぞれが常時バージョンアップを進行させています。
このことにより、せっかく作成したデータベースが例えばMySQLのバージョンアップにより構造から作り直さなくてはならない、となると非常に煩雑な作業を行わなくてはなりません。
マイグレーションによりデータベースの構造、つまりテーブルやカラムの形を定義して、土台のエータベースシステムに変更があった場合でも簡単に作成したデータベースが再現できます。
その意味では構造管理でもありバージョン管理機能も兼ね備えている、と言っていいでしょう。
マイグレーションファイルはプロジェクトルートディレクトリ以下 database>migration ディレクトリに生成されます。
生成はコマンドプロンプト、あるいはPower Shell からLaravelのartisan コマンドを打って行います。
php artisan make:migration create_corporations_table
corporationsが作りたいテーブル名です。複数形になっている点留意しておいてください。
create_corporations_table はcorporationsというtableをcreateしなさい、という指示文です。
コマンドをEnterします。
Created Migration: 2021_07_07_135620_create_corporations_table
このようなメッセージが表示されたらマイグレーションファイルの生成が完了です。
ディレクトリ database>migrations ディレクトリの中に「2021_07_07_135620_create_corporations_table.php」というファイルが出来上がっています。
これがマイグレーションファイルです。
ファイル名は自動的に生成されます。前半はファイルを生成した年月日時刻、そのあとにコマンドで打った指示文が続きます。
ここにマイグレーションファイルを作成して必要項目を書き込み、php artisan migrate とコマンドを叩けばSQLのCreate Table corporations{} のと同じ仕事をマイグレーションがしてくれるわけです。
実演の前に、migrationsディレクトリ内の他のファイルを削除してください。
使うことはないので削除で構いませんがVisual Studio Code なら削除の際にRecycle Bin に退避させてくれるのであとで復活可能です。
そのうえで「2021_07_07_135620_create_corporations_table.php」を開きます。
マイグレーションファイルを作成すると基本構文はすでに記述されています。
大きな説明をすると、
①まずこのファイルは
・Migration
・Blueprint
・Schema
の3つのクラスを引用して作成されています。
②そしてCreateCorporationsTableというクラスをMigrationを継承してここに作られます。
③そしてCreateCorporationsTableはMigrationにあるup() とdown() の2つのメソッドから構成されて います。
up()はcreateやaddの実行、down()は削除を行うメソッドです。
up()の中で、テーブルの作成はSchemaクラスのcreateメソッド、フィールド(カラム)の設定はBlueprintクラスのメソッドで行い、その結果を$table という変数にしてcreateメソッドの第二引数に渡しています。
このなかにすでに
$table->id();
$table->timestamps();
の2行が記述されていますが、前者はレコードの通し番号、後者はレコード作成時のタイムスタンプで、テーブル作成時に設置が推奨されています。
down()の中にはSchemaからのdropメソッドがすでに記述されています。dropあとのIfExists は引数のテーブルがあったなら、という意味です。
Blueprintのメソッドでフィールドの定義を行ってゆきたいと思います。
基本的には
$table->increment(id);
という形ですincrementのところにデータ型、()内にフィールド名を定義してゆきます。
大体長さ(Length)は第二引数で指定できるようなので、それぞれ定義します。
一意(Unique)であるフィールドについては追加で->unique()を加えます。
NULLがOKなフィールドも->nullable()の追加で属性化します。
プライマリキーの設定も->primary()で'Corp_id_f'に追加定義します。
$table->id('id');
$table->char('Corp_id_f',25)->unique()->primary();
$table->char('Corp_nm_f',75);
$table->char('Corp_addr_f',150)->nullable();
$table->char('Corp_tel_f',40)->unique();
$table->char('Corp_dept_f',40)->nullable();
$table->char('Corp_mail_f',75)->unique();
$table->char('Corp_pw_f',15);
$table->char('Corp_adpw_f',20);
$table->timestamp('Corp_reg_f');
さらにup()のメソッドの中、Schema::createをif文で囲みます。
if(!schema::hasTable('corporations')){
Schema::create(・・・・・);
}
データベースが'corporations'というテーブルを持って(hasTable)いなければ(!)、'corporations'を作れ、という指示です。
Blueprintのメソッド、特にカラム定義(columnDefinition)についてはこちらのリファレンスに詳細が掲載されています。
https://laravel.com/api/8.x/Illuminate/Database/Schema/Blueprint.html
こうしてマイグレーションファイルの準備ができたら、このファイルを実行します。
artisanコマンドで
php artisan migrate
を叩きます。
ここでVisual Code Studio のTerminal機能でartisanコマンドを打ってみます。
Visual Code Studioの最上部メニューバーにあるTerminal→New Terminal でPowerShellが起動します。
最初からディレクトリがDMENAになっていますのでCMDを呼び出すのに比べ格段に作業がはかどります。
ステータスがMigrating→Migrateに変化してマイグレーションファイルの実行が完了します。
ここで、目論見通り「dmena」データベースに「corporations」テーブルができているか確認します。
Xampp Control PanelからPHP MyAdminを起動させます。
dmena 配下にcorporationsテーブルが生成されています。
定義したフィールド群も目論見通り生成されています。
Migrationを利用して、このようにしてテーブルやフィールドといったデータベースの構成管理を行います。
モデルの作成
先回の投稿で説明した通り、Laravel はMVCモデルに基づいて構成されており、MVCのMはModelであり、Modelはデータベースの操作やデータのオブジェクト化に関して責任を持っています。
LaravelにはEloquent ORM(Object Relational Mapping)という機能が実装されています。ORMとは2つのシステム間で本来互換性のないデータを行き来させるための翻訳機能です。
Eloquent ORMはLaravelで動くPHP(ControllerやView)とMySQLなどのDB間の仲介を行います。
Eloquent ORMには様々な機能が実装されており、特にMVCの中でAPI的な機能を果たすプロパティやメソッドを集めたModelというクラスがあります。
(マイグレーションもEloquantが持つクラスの一つです)
開発者はこのModelクラスを継承したクラスファイルを作成し、そのアプリケーション個別のカスタマイズをしてMVCモデルにおけるデータベース制御の橋頭保にします。
アプリケーション用のModelクラスはアプリケーションのデータベーステーブルと関連付けられている必要があります。
そのためにネーミングルールがあります。
先に触れたようにここでは「corporations」というテーブルをマイグレーションを使って作成しています。
このテーブルに関連付けるModelクラスの名称は「Corporation」とします。
・テーブル名の先頭文字を大文字にする
・テーブル名を複数形にして、Modelクラス名では単数形にする
Ex.テーブル名:Companies クラス名:Company
Modelクラスはartisanコマンドで生成します。
php artisan make:model Corporation
Model created successfully. というメッセージが表示されたらモデルの生成が完了します。
app>Models デイレクトリに「Corporation.php」が生成されていることが確認できます。(以下Corporationモデルと呼ぶ)
Corporationモデルの中にはデフォルトでいくつかの記述がなされています。
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
はそれぞれ、EloquentのHasFactoryクラス、Modelクラスを継承する旨の宣言です。
次のclass Corporation extends Model{} の中にDMENA特有のプロファイルや機能を記述してゆきます。
use HasFactory;
の下最初に記述すべきなのが、
protected $table = 'corporations';
です。
実は先に触れたようにクラス名と対応テーブル名の間のネーミングルールに則っていればこの行は不要です。
が、存在しても実害はないので備忘録的に記述しておきます。
次にテーブルにおけるプライマリーキーの指定です。
マイグレーションを生成する際にデフォルトで
$table->id();
というプロファイル指定がありました。
これはこのまま残すと'id'というオートインクリメンタルなフィールドができ、それがプライマリーキーになります。
しかし、今回は'id'とは別に'Corp_id_f'というフィールドを設け、それをプライマリーキーにしました。
$table->id('id');
$table->char('Corp_id_f',25)->unique()->primary();
これでLaravel上で'Corp_id_f'がプライマリキーになったかというと十分ではなく、Corporationモデルでもそれを定義する必要があるのです。
Corporationモデルに
protected $primaryKey = 'Corp_id_f';
と定義します。
次に書くフィールドに対してfillableとguarded を指定します。
fillable というのはLaravelがInsertやUpdateなどの操作ができるフィールド指定です。ホワイトリストを指定するようなものです。
逆にguarded はLaravelからの操作を禁止したいフィールドです。こちらはブラックリスト的にあものになります。
今回、corporations テーブルのほとんどのフィールドはユーザーからの入力情報で満たされ(fill)るので'id'と'Corp_reg_f'以外はfillableにしておきます。
'Corp_id_f','Corp_pw_f','Corp_adpw_f'はサーバー側で生成する予定なので、これらもfillableにするのは悩ましいところですが、今後の学習の中で必要に応じて修正します。
protected $fillable = [
'Corp_id_f',
'Corp_nm_f',
'Corp_addr_f',
'Corp_tel_f',
'Corp_dept_f',
'Corp_mail_f',
'Corp_pw_f',
'Corp_adpw_f'
];
これを保存してCorporationモデルを確定させるとMVCのM側の準備は完了です。
ちなみにLaravelでデータベースを動かす場合、DBクラスを使ってControllerのメソッドに直接クエリを書く、というやり方も可能です。
しかし、この場合受け渡しされるデータは連想配列という形でオブジェクト化されます。
連想配列を理解して、PHPで紐解けばデータはLaravel側(ControllerやView)でもいろいろな形で利用できるのですが、オブジェクト自体をLaravel側でネイティブに扱うことはできません。
その点、Eloquent Modelに基づくオブジェクトはLaravel側でネイティブに扱うことができ、設計の自由度が格段に上がります。
次回はMVC+RのR、ルーティングについて解説をしてゆきます。
Comments