データーベースの利用2 Modelの利用 #Laravel頻出パターン
# はじめに
Laravelを使ったプログラミングは小さな積み重ねが重要です。Laravel頻出パターンとして独立した形でよくあるパターンをまとめました。
本稿ではデーターベースを実際にWebアプリケーションで利用するために必要なModelについての知識をまとめています。
サンプルプロジェクトの作成で必須となりますので、用語なども覚えましょう。
用語
・Model
・ORM
・MVCアーキテクチャ
・Collection
# 課題
本稿の課題はこちらです。
・Modelクラスを作成すること
・SeederをModelクラスを利用して作成すること
・Modelを利用したデータの取り出し方法について学ぶこと
# 準備:「user_entry」テーブルの作成
まずはデーターベースに接続するための準備を行います。
こちらの記事を参考にデーターベースに接続可能なLaravelのアプリケーションを作成してください。
データーベースの利用の記事で作成した「user_entry」テーブルを例に開発を進めます。
テーブル作成のためのクラスのコードは以下のような形になります。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUserEntryTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('user_entry', function (Blueprint $table) {
$table->id();
$table->string('title'); //タイトル
$table->string('body'); //本文
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('user_entry');
}
}
# Modelクラスの作成
Laravelはアプリケーションの機能をModel-View-Controllerという3つの層に分割する、MVCモデルと呼ばれる設計で出来ています。
それぞれ次の役割があります。
・Model層 - システム内のビジネスロジックを担当(Modelクラス)
・View層 - 表示を行う機能(bladeテンプレートなど)
・Controller層 - ユーザーの操作に基づいてModelとViewを制御する(Controllerクラス)
Laravel通りに開発を進めると自然とMVCモデルに分割した形になっていきます。
今から作成するModelクラスは、MVCモデルのModel層に含まれる「データーベースとやりとりをする機能」を持つクラスです。
◆
Modelクラスの作成には「make:model」コマンドを利用します。make:modelコマンドは次の形式です。
php artisan make:model クラス名
では、user_entryテーブルに対応するUserEntryクラスを作成します。
ターミナルを起動し、次のコマンドを入力してください。
php artisan make:model UserEntry
「Model created successfully.」と表示されたら成功です。
appディレクトリの下にUserEntry.phpが作成されています。
作成直後は次のようなファイルです。
app/UserEntry.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class UserEntry extends Model
{
//
}
現在の内容ではテーブル名との関連付けが出来ていないため、テーブル名の設定を追加します。テーブル名の設定を追加するには$tableパラメーターに値を設定します。
protected $table = "<テーブル名>";
UserEntryクラスを「user_entry」テーブルに関連付けるコードは次のようになります。
app/UserEntry.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class UserEntry extends Model
{
protected $table = "user_entry";
}
UserEntryクラスはuser_entryテーブルと対応するクラスです。
このようにデーターベースとプログラムのコードを対応させ、利用しやすく設計を「ORM(Object-Relation-Mapping)」と呼びます。
# Modelのテスト
Modelが上手く動いているかを確認するために、テストするためのコントローラーを作成します。
コントローラーとルーティングについては【Laravelを使ったウェブサイトの開発】で詳しく解説しているため、わからない方はそちらをご確認ください。
コントローラーの作成は手動で行うことも出来ます(上記記事では手動で作成)が、Laravelにはコントローラーを作成するための「make:controller」コマンドが用意されています。
ターミナルで次のコマンドを実行してください
php artisan make:controller UserEntryController
実行すると「app/Http/Controllers/UserEntryController.php」が作成されます。
作成されたコントローラーを編集して、全てのデータを表示するindex()関数を作成します。
app/Http/Controllers/UserEntryController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\UserEntry;
class UserEntryController extends Controller
{
function index(){
$all = UserEntry::all();
dd($all);
}
}
use App\UserEntry;
こちらは作成したクラスを読み込むためのコードです。クラスの宣言より前にuse句を使ってUserEntryクラスを読み込みます。
$all = UserEntry::all();
「モデルクラス::all()」はModelの機能でUserEntry(user_entryテーブル)の全てのデータを取得する機能です。
dd($all);
これはLaravelのヘルパー関数と呼ばれる便利な関数で引数で指定したデータをdumpして終了するデバッグ用の関数です。終了しないdump()関数もあります。
◆
続いて、作成したUserEntryControllerをルーティングに設定します。
routes/web.php
Route::get('/user_entry', "UserEntryController@index");
ブラウザで「http://127.0.0.1:8000/user_entry」にアクセスしてください。
サーバーを起動していない場合は次のコマンドを実行してサーバーを起動してください。
php artisan serv
次のように表示されていれば成功です。
ddで出力した内容はクリックで展開出来ます。「attributes」を見ると実際に取得出来た内容が確認出来ます。
テーブル名が違う、クラス名が違うなどがあればそれぞれエラーが表示されます。動作しない人は次のことを確認してください
・Seederは実行済みですか?「php artisan db:seed」コマンドを実行してください
・ルーティングの設定、Controllerの作成などが問題ないか
・UserEntryクラスで関連付けているテーブル名が正しいか
# SeederでModelの利用を行う
データーベースを利用の記事では「DB::table('user_entry')->insert(...)」を使って直接データーベースを操作していましたが、この部分はModelを利用する形に変更できます。
database/seeds/UserEntrySeeder.php
<?php
use Illuminate\Database\Seeder;
use App\UserEntry;
class UserEntrySeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
UserEntry::create([
"title" => "UserEntryクラスで作成したtitle",
"body" => "UserEntryクラスで作成したbody"
]);
}
}
use App\UserEntry;
Controllerで記載したのと同様に、クラスの宣言より前にuse句を使ってUserEntryクラスを読み込みます。
データの挿入部分は次のように書き換わっています
DB::table('user_entry')->insert([
'title' => "ダミータイトル",
'body' => "ダミー本文です",
'created_at' => date("Y-m-d H:i:s")
]);
↓
UserEntry::create([
"title" => "UserEntryクラスで作成したtitle",
"body" => "UserEntryクラスで作成したbody"
]);
このように「モデルのクラス名::create()」関数でレコードを追加することが出来ます。DB::table()->insert()を使う形と異なり、created_atを入れる必要がないことに注意してください。
created_atとupdated_atはModelクラスの機能を利用した場合、自動的に追加されます。このようにModelクラス経由であればデーターベースについて意識せずに利用することが出来ます。
変更が終わりましたら、次のコマンドを実行して、Seederを実行して動作を確認してください。
php artisan db:seed
phpMyAdminで作成されたレコードがどのような形で保存されているか確認すると次のようになっています。
Model::create()を使った場合はcreated_at、updated_atが正しく入っていることがわかります。
# Modelクラスを利用したデータの取得方法
UserEntryControllerを改造し、色々なModelを利用した取得パターンを試してみましょう。
何度かSeederを実行して5件ほどのデータを作成しておきましょう。
Modelクラスで取得した結果が複数件になる場合は「Collection」と呼ばれる形でまとめて取得されます。呼び出し方法では結果が1件の場合でもCollectionになる場合があるので注意してください。
データの取得方法には非常に多くのパターンがありますが、簡単なよく使うものをリストアップしました。
こちらをUserEntryControllerクラスのindex()メソッドに書いて、一件毎に動作の確認をしてみてください。
dump()関数はdd()と違って表示した後に終了しないものです。
//先頭を取得
$entry = UserEntry::first();
dump($entry);
結果:ID=1のUserEntryが表示
//ID=1を取得
$entry = UserEntry::find(1);
dump($entry);
結果:ID=1のUserEntryが表示
//ID=2を取得
$entry = UserEntry::find(2);
dump($entry);
結果:ID=2のUserEntryが表示
//存在しないIDを指定した場合
$entry = UserEntry::find(999);
dump($entry);
結果:nullが表示
複数件の取得を行う場合は、where()メソッドを使います。
//whereを利用してID指定(id=2)
$entry_list = UserEntry::where("id", 2)->get();
dump($entry_list);
結果:ID=2のUserEntryが含まれたCollectionが表示
//whereを利用してID指定し、Collectionから一件取得
$entry = UserEntry::where("id", 2)->first();
dump($entry);
結果:ID=2のUserEntryが表示
//whereを利用してIDが2より大きいものを取得
$entry_list = UserEntry::where("id", ">", 2)->get();
dump($entry_list);
結果:ID=3〜7のUserEntryが含まれたCollectionが表示
これらの操作は実際に手を動かして一件ずつ動作を確認したほうがわりやすいです。一度試してみてください。
# findを使った詳細ページの作り方
最後に応用例とはなりますが、UserEntryControllerクラスを修正して詳細ページを作ってみましょう。
まずはUserEntryControllerにidを引数に持つdetail関数を作成します。
app/Http/Controllers/UserEntryController.php
class UserEntryController extends Controller
{
(略)
function detail($id){
$item = UserEntry::find($id);
return view("user_entry_detail", ["item" => $item]);
}
}
detail($id)関数は「user_entry_detail」テンプレートに取得したUserEntryを渡す機能を持っています。
次にルーティングを設定します。
routes/web.php
Route::get('/user_entry/{id}', "UserEntryController@detail");
このようにURLを/user_entry/{id}と指定することで/user_entry/1でアクセスしたらdetail(1)を呼び出すことが出来ます。
最後にuser_entry_detailテンプレートを作成します。
resources/view/user_entry_detail.blade.php
<ul>
<li>ID: {{ $item->id }}</li>
<li>Title: {{ $item->title }}</li>
<li>Body: {{ $item->body }}</li>
</ul>
テンプレートの作成が完了したら、ブラウザで次のURLを開いて動作を確認してみてください。
・http://127.0.0.1:8000/user_entry/1
・http://127.0.0.1:8000/user_entry/2
次のように表示されていれば成功です。
表示できない人は次のことを確認してください
・関数名とルーティングの設定は正しいですか?
・テンプレートのファイル名は「user_entry_detail」になっていますか?
・phpMyAdminなどを利用してデータが正しく入力されていますか?
# まとめ
本稿を振り返り、LaravelでModelクラスを利用したデーターベースからの値の取り出しについて確認してください。
詳細ページの作り方はWebアプリケーションで必ず出てくる内容です。データーベースのIDとfind()を使った値の取得は覚えましょう。
おつかれさまでした!
---