概要
Laravelにおけるデータモデルの操作をまとめる。
例としてStickyNoteというアプリケーションを仮定する。StickyNoteは付箋紙のようなアプリケーションで、タイトルとメモ本文を扱う。このアプリケーションを通して、フォーム入力、データの読み込み、書き込み、更新、削除の流れをそれぞれ整理。
データ構造
マイグレーションファイル
マイグレーションファイルにより、StickyNotesの個々の付箋メモのデータ構造を定義。タイトル(title)とメモ本文(body)を定義している。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class CreateDiariesTable extends Migration { ..... public function up() { Schema::create('diaries', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('title', 20); $table->string('title', 100); $table->datetime('created_at'); $table->datetime('updated_at'); }); } ..... } |
データベース
マイグレーションの結果得られるテーブルの構造。
|
1 2 3 4 5 6 7 8 9 10 11 |
mysql> describe diaries; +------------+-----------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+-----------------+------+-----+---------+----------------+ | id | bigint unsigned | NO | PRI | NULL | auto_increment | | title | varchar(20) | NO | | NULL | | | body | varchar(100) | NO | | NULL | | | created_at | datetime | NO | | NULL | | | updated_at | datetime | NO | | NULL | | +------------+-----------------+------+-----+---------+----------------+ 5 rows in set (0.00 sec) |
データの読み込み
ルーティング
ドメイン名/sticky_noteのURL指定に対してコントローラーStickyNoteControllerのindexアクションを呼び出す。
routes/web.php
|
1 |
Route::get('/sticky_note', 'StickyNoteController@index'); |
コントローラーでの処理~all()による全データ取得
全データ取得はコントローラーのスタティックメソッドall()を使い、結果はレコード単位の配列で得られる。
ここでは、
indexアクションで$sticky_notesに表示対象の全データを取得- 取得した配列をビューに渡して遷移
- モデルを記述するときはフルパスで書くか冒頭で
use宣言
app/Https/Controllers/StickyNoteController.php
\App\StickyNoteのようにモデルをフルパスで指定する必要がある。あるいは冒頭でuse \App\StickyNoteとしてもよい。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class StickyNoteController extends Controller { ..... public function index() { // データベースから全データ取得 $sticky_notes = \App\StickyNote::all(); // ページ遷移 return view('sticky_note.index', [ 'title' => '付箋紙', 'sticky_notes' => $sticky_notes, ]); } ..... } |
ビューによる表示
ビューで受け取った配列をループで表示させている。データベースのカラムに対応した属性で、各カラムのデータが得られる。
resources/views/sticky_note/index.blade.html
|
1 2 3 4 5 6 |
@forelse ($sticky_notes as $sticky_note) <div>{{ $sticky_note->title }}</div> <div>{{ $sticky_note->body }}</div> @empty <p>付箋紙が登録されていません。</p> @endforelse |
データの書き込み
フォームでの入力と送信
書き込むデータをフォーム入力し、POTSTで送信する。
resources/views/create.blade.php
|
1 2 3 4 5 6 7 8 9 10 |
<form method="post" action="/sticky_note"> @csrf <div> <label>タイトル: <input type="text" name="title"></label> </div> <div> <label>メモ内容: <input type="text" name="body"></label> </div> <input type="submit" value="送信"> </form> |
ルーティング~POSTに対する書き込み処理
POSTのルーティング先をコントローラーのstore()アクションとしている。
routes/web.php
|
1 |
Route::post('/sticky_note', 'StickyNoteController@store'); |
コントローラーでの処理~create()によるデータ書き込み
ルーティング先のアクションではフォームリクエストを引数にとり、マスアサインメントと登録処理を1行で記述している。
また、アクションで引用するモデルとフォームリクエストのクラスをuseでインポートしている。
ここでは、
- コントローラーの冒頭で、モデル
StickyNoteとフォームリクエストStickyNoteRequestをuseでインポート - フォームリクエスト
StickyNoteRequestを引数にとっている - リクエストの
only()メソッドでマスアサイン - アサイン結果をモデル
StickyNoteのcreate()スタティックメソッドの引数に与え、データを登録 - トップページにリダイレクト
app/Https/Controllers/StickyNoteController.php
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// カスタムモデル use App\StickyNote; // カスタムフォームリクエスト use App\Http\Requests\StickyNoteRequest; class StickyNoteController extends Controller { ..... public function store(StickyNoteRequest $request) { // マスアサインメント結果をDBに新規登録 StickyNote::create($request->only(['title', 'body'])); // トップページにリダイレクト return redirect('/sticky_note'); } ..... } |
モデルでの$fillable定義
コントローラーでのマスアサインメントを有効にするため、データモデルで$fillableプロパティーを定義。
ここでは、StickyNoteモデルクラスで$fillableをpublic宣言して、読み込むプロパティーをtitleとbodyの2つに限定している。
app/StickyNote.php
|
1 2 3 4 |
class StickyNote extends Model { public $fillable = ['title', 'body']; } |
データの更新
ルーティング
- 更新対象を指定するデータの
idがルートパラメーターで指定されてGETされることを想定- URLにルートパラメーター
{id}を含めている - GETメソッドでトップページなど他のページを区別するために、URLに
/editを付けている
- URLにルートパラメーター
- GETを受け取ったら
editアクションにルーティング - たとえばアンカータグでここに飛ばしたい場合は、
url()ヘルパーを使って以下のように指定する<a href="{{ url('/diaries') . '/' . $diary->id . '/edit' }}">
routes/web.php
|
1 2 |
Route::get('/sticky_note/{id}/edit', 'StickyNoteController@edit') ->where('id', '^\d+$'); |
コントローラーでの処理~find()による更新対象の取得
- ルーティングで設定されたルートパラメーターは、アクションの引数で参照する
- モデルの
find()スタティックメソッドで、idに対応するモデルのインスタンスを取得 - 取得したモデルインスタンスを、更新用のフォームを持つビューに渡す
- 遷移先のビューで
idに対応するデータを初期表示するため
- 遷移先のビューで
app/Https/Controllers/StickyNoteController.php
|
1 2 3 4 5 6 7 8 9 |
public function edit($id) { // ルートパラメーターから更新するインスタンスを取得 $sticky_note = \App\StickyNote::find($id); // 更新するインスタンスを渡して編集ページを表示 return view('edit', [ 'title' => '内容編集', 'body' => $body, ]); } |
フォームでの入力と送信
- 更新用のフォームを表示する
- フォームの各要素に、受け取ったデータのタイトルと本文を初期表示する
- 更新結果はPATCHメソッドで送信
- HTTPにはGETとPOSTしかないので、
formタグではPOSTを指定し、@method()ディレクティブでPATCHを指定している - 送信先の
actionで、idをルートパラメーターとして付加している
- HTTPにはGETとPOSTしかないので、
resources/views/edit.blade.php
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<form method="post" action="{{ url('/sticky_note') . '/' . $sticky_note->id }}"> @csrf @method('PATCH') <div> <label>タイトル: <input type="text" name="title" value="{{ $sticky_note->title }}"> </label> </div> <div> <label>メモ内容: <input type="text" name="body" value="{{ $sticky_note->body }}"> </label> </div> <input type="submit" value="保存"> </form> |
ルーティング
PATCHメソッドによるルートパラメーターidを含むURLへの送信を、update()アクションにルーティング。
routes/web.php
|
1 2 |
Route::patch('/sticky_note/{id}', 'StickyNoteController@update') ->where('id', '^\d+$'); |
コントローラーでの処理~update()による更新処理
データの書き込みと同じような手順。
- ルートパラメーターを引数で受け取り
- 引数の順番は、フォームリクエスト、ルートパラメーターの順番
find()の引数にidを与えてデータを取得- マスアサインメントでデータを更新
- トップページへリダイレクト
app/Https/Controllers/StickyNoteController.php
|
1 2 3 4 5 6 7 8 |
public function update(StickyNoteRequest $request, $id) { // ルートパラメーターから更新するインスタンスを取得 $diary = \App\StickyNote::find($id); // マスアサインメント結果をで更新 $diary->update($request->only(['title', 'body'])); // トップページへリダイレクト return redirect('/sticky_note'); } |
データの削除
ビュー~削除対象指定
- 全データを表示する際に、各データをフォームで表示し、データごとに削除ボタンを置く
- 削除ボタンが押されると、DELETEメソッドで
idをルートパラメーターに含むURLを呼び出す - HTTPにはGETとPOSTしかないため、@methodディレクティブでDELETEを指定
routes/web.php
|
1 2 3 4 5 6 7 8 9 10 |
@forelse ($sticky_notes as $sticky_note) <form method="post" action="{{ url('/sticky_note') . '/' . $sticky_note->id }}"> @csrf @method('DELETE') <div>{{ $sticky_note->title }}</div> <input type="submit" value="削除"> </form> @empty <p>付箋紙が登録されていません。</p> @endforelse |
ルーティング
DELETEメソッドで所定のURLが要求された場合に、destroy()アクションにルーティング。
routes/web.php
|
1 2 |
Route::delete('/diaries/{id}', 'DiaryController@destroy') ->where('id', '^\d+$'); |
コントローラーでの処理~delete()による削除
- ルートパラメーターで受け取ったidでデータを取り出し
- 得られたデータを
delete()で削除 - トップページにリダイレクト
app/Https/Controllers/StickyNoteController.php
|
1 2 3 4 5 6 7 8 |
public function destroy($id) { // ルートパラメーターから削除する対象を取得 $Sticky_note = \App\StickyNote::find($id); // 対象を削除 $Stocky_note->delete(); // トップページへリダイレクト return redirect('/sticky_note'); } |