データベースとの連携(5)CRUD
データベース連携の最後のまとめとしてCRUDを実装した簡単なWebシステムを実装します。
「CRUD」とは、「Create」レコードの作成、「Read」レコード読み込み、「Update」レコードの更新、「Delete」レコードの削除機能を作成します。
ルーティング、コントローラー、モデル、ビューの各役割りと連携、データのライフサイクルを確認しながら学んでいきましょう。
CRUDの仕様
◆実装機能
①会員登録
会員情報を登録する機能
②一覧画面
全会員情報をデータベースから取得して会員一覧を画面出力
③会員情報更新
登録済み会員情報を入力フォームに表示して内容の修正更新が出来る
④会員情報の削除
登録した会員情報を削除できる
データベースのテーブル仕様
新規データベース「crud」を作成
id(登録番号)を「主キー」にして全項目入力必須とします(Not Null)
フィールド名 | データ型 | 備考 |
---|---|---|
id | integer | 登録番号(自動採番) |
name | varchae(64) | 氏名 |
age | tinyinteger | 年齢 |
varchae(256) | メールアドレス | |
created_at | datetime | 登録日時 |
updated_at | datetime | 更新日時 |
画面レイアウト
画像1:初期アクセス画面(一覧)
画像2:新規入力フォーム
画像2:編集入力フォーム
環境準備
CRUDプロジェクトの作成
≪Larvel プロジェクトの導入はこちら≫
マイグレーションファイルの作成
先に作成したデータベースのテーブル仕様に従ってマイグレーションファイルを作成しましょう。
今回は、membersテーブルなので、
1 |
php artisan make:migration create_members_table |
作成したマイグレーションファイルを編集
1 2 3 4 5 6 7 8 9 10 |
public function up() { Schema::create('members', function (Blueprint $table) { $table->increments('id'); $table->string('name',64); $table->tinyinteger('age'); $table->string('mail'); $table->timestamps(); }); } |
マイグレーションの実行
1 |
php artisan migrate |
Larvelプロジェクトの環境設定ファイル「.env」に追記
コントローラファイルの作成
1 |
php artisan make:controller MemberController |
app/Http/Controllers/MemberController.php
1 2 3 4 5 6 7 8 9 10 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class MemberController extends Controller { // } |
モデルファイルの作成
1 |
php artisan make:model Member |
app/Http/Models/Member.php
1 2 3 4 5 6 7 8 9 10 11 |
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Member extends Model { use HasFactory; } |
登録プログラムの作成【Create】
ルーティングの設定
routes/web.php に以下の記述を追加
一覧画面を表示する為のルーティング
1 |
Route::get('/member', [App\Http\Controllers\MemberController::class, 'index']); |
このルーティングでは、Memberコントローラのindexメソッドを呼び出している
コントローラにindexメソッドの作成
初期アクセス画面を表示するためメソッドを作成
(先のルーティングから呼び出されている)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class MemberControlles extends Controller { public function index() { //view関数でindex.blade.phpを出力 return view('index'); } } |
初期画面レイアウトファイルを作成
resources/views/index.blade.php
index.blade.phpソース内の新規登録のアンカーリンクに“/member/form”を指定する。
1 2 3 4 5 6 7 8 9 10 11 12 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>新規登録</title> </head> <body> <a href="/member/form">新規登録</a> </body> </html> |
ルーティングの追加
新規登録のリンクをクリックした場合のリクエスト対応として、
routes/web.phpにルーティングを追記
1 |
Route::get('/member/form', [App\Http\Controllers\MemberController::class, 'form']); |
MemberControllerにformメソッドを追加
ルーティングからのメソッド呼び出しを受けれるようにする
1 2 3 4 |
public function form() { return view('form'); } |
このメソッドは、bladeファイルを呼び出している
新規登録用のレイアウトファイルを作成
新規登録ボタンを押された時にメソッドから呼び出されるbladeファイル
resources/views/form.blade.php
入力フォームのソース
formリクエストは、POST送信で送信先は「store」にする。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>入力フォーム</title> </head> <body> <form action="/member/store" method="post"> @csrf <table> <tr> <th>氏名</th> <td><input type="text" name="name" required></td> </tr> <tr> <th>年齢</th> <td><input type="number" name="age" required></td></td> </tr> <tr> <th>メールアドレス</th> <td><input type="email" name="mail" required></td></td> </tr> </table> <input type="submit" value="送信"> </form> </body> </html> |
入力フォームからPOST送信する際は「@scrf」の記述がないとエラーになります。
CSRF(クロスサイトリクエストフォージェリ)はWebシステムを悪用したサイバー攻撃でこの1行はこれを防ぐ対策です。
送信ボタンを押した場合のURLに対応するルーティングを追加
routes/web.phpにルーティングを追記
1 |
Route::post('/member/store', [App\Http\Controllers\MemberController::class, 'store']); |
(このルーティングは、POSTリクエストを受け取るのでpostメソッドを使っている)
ここでは、MemberControllerのstoreメソッドを呼び出している
MemberControllerにデータベース登録用のstoreメソッドを追加
このコントローラには、クエリを記述するのでファイルの冒頭でモデルの読み込みを追加しておく
(これがないとMemberモデルに対するクエリを実行できない)
1 |
use App\Models\Member; |
app/http/controllers/MemberContoroller
1 2 3 4 5 6 7 8 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Member; class MemberController extends Controller |
このメソッドは、リクエストパラメータを受け取れるようにメソッドの引数にリクエスト変数を入れておきます(依存性の注入【DI】については別の学習であらためて説明します)。
メソッド内でユーザーから送信されたリクエストの値を扱えるようになります。
1 2 3 4 5 6 7 8 9 10 11 |
public function store(Request $request) { Member::create([ 'name' => $request->name, 'age' => $request->age, 'mail' => $request->mail, ]); //登録処理後、一覧画面に遷移する return redirect('/member'); } |
ここでは、createメソッドを使ってデータベースに登録しています。
引数に連想配列を指定して、「key」にデータベースのフィールド名、「value」に登録する値を指定します。
登録が完了すると初期画面に戻るようにリダイレクト処理を最後に記述しています。
Memberモデルに登録
モデルを介してデータの登録・更新をする場合は、$fillableプロパティを設定して対象のフィールドを配列として加える必要があります。
1 2 3 4 5 |
class Member extends Model { use HasFactory; protected $fillable = ['name','age','mail']; } |
ブラウザでの登録操作と登録データの確認
Laravelの起動
1 |
php artisan serve |
http://127.0.0.1:8000/member
データを登録しよう
データベースのmembersテーブルを確認するとデータが登録されているあずです。
(データベースクライアントを使って確認してください)
登録レコードの読込【Read】
データの登録処理は、完成したのでレコードを表示できるようにしましょう。
コントローラのindexメソッドを編集
一覧出力をするためにindexメソッドにデータ取得のクエリを追記する
クエリの取得データをview関数の第2引数に設定
これにより呼び出されたbladeファイル(index.blade.php)で結果の値を扱える
1 2 3 4 5 6 7 8 |
public function index() { //Memberモデルを指定し全ての登録レコードを取得 $members = Member::all(); //view関数でindex.blade.phpを出力(Bladeファイルで扱えるように第2引数にクエリで取得した値を設定) return view('index',['members' => $members]); } |
初期画面用のレイアウトファイルを編集(blade)
index.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>新規登録</title> </head> <body> <h1>一覧</h1> <a href="/member/form">新規登録</a> <table> <tr> <th>登録番号</th> <th>氏名</th> <th>年齢</th> <th>メール</th> <th>更新日時</th> </tr> @foreach($members as $member) <tr> <td>{{ $member->id }}</td> <td>{{ $member->name }}</td> <td>{{ $member->age }}</td> <td>{{ $member->mail }}</td> <td>{{ $member->updated_at }}</td> </tr> @endforeach </table> </body> </html> |
≪bladeの変数出力やディレクティブの詳しい説明こちら≫
ブラウザで出力確認
Laravelの起動
1 |
php artisan serve |
http://127.0.0.1:8000/member
登録データが初期画面に表示されています。
追加で登録処理を行うと即座に反映されます。
登録レコードの更新【uodate】
登録済みデータの編集を実装しましょう。
編集は一覧出力のレコードの氏名にアンカーリンク設定し、クリックしたら編集画面が開くようにしましょう。
一覧出力の氏名にアンカータグで囲む(blade)
index.blade,php(部分抜粋)
この氏名の出力ソースを修正します。
1 |
<td>{{ $member->name }}</td> |
修正後のソースのアンカーリンクの遷移先は、「/member/edit/登録番号」
1 |
<td><a href="/member/edit/{{ $member->id }}">{{ $member->name }}</a></td> |
編集の際、レコードを特定する必要があるのでアドレスに登録番号を含めています
編集画面表示用のルーティングを追加
1 |
Route::get('/member/edit/{id}', [App\Http\Controllers\MemberController::class, 'edit']); |
ルーティングの第1引数のURL部分に“{ルートパラメータ}”を記述すると呼び出したコントローラのメソッド側でリクエストパラメータとして取得できるようになります。今回は、パラメータ名を「id」としているので、コントローラのメソッド(edit)で、$request->id で取得できます。
コントローラにeditメソッドを追加
データベースのmemberテーブルからアンカータグでクリックされた登録番号のレコード情報を1件取得して編集用入力フォームに取得データを渡す。
1 2 3 4 5 |
public function edit(Request $request) { $member = Member::find($request->id); return view('edit',['member' => $member]); } |
レコード編集用のフォームレイアウトを作成(blade)
先に作成したform.blade,php をコピーしてedit.blade.phpを作成する
変更箇所
①登録番号の表示
②送信アドレスの変更 action=”/member/update”
③inputコントロールにvalue属性を追加してデータベースから取得した登録データをセットする。
④このレコードの登録番号も送信データに含めるためinputコントロールのtype属性をhiddenにしたコントロールを追加する。
resources/views/edit.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>入力フォーム</title> </head> <body> 登録番号:{{ $member->id }} <form action="/member/update" method="post"> @csrf <table> <tr> <th>氏名</th> <td><input type="text" name="name" value="{{ $member->name }}" required></td> </tr> <tr> <th>年齢</th> <td><input type="number" name="age" value="{{ $member->age }}" required></td></td> </tr> <tr> <th>メールアドレス</th> <td><input type="email" name="mail" value="{{ $member->mail }}" required></td></td> </tr> </table> <input type="submit" value="送信"> <input type="hidden" name="id" value="{{ $member->id }}"> </form> </body> </html> |
form.blade.phpを使って共通利用もできますが、ソースが複雑になるので別ファイルを作成してシンプルな表記にしています。
編集データの更新用ルーティングを追加
編集フォームのaction属性に対応した以下のルーティングを追記
1 |
Route::post('/member/update', [App\Http\Controllers\MemberController::class, 'update']); |
MemberControkkerのupdateメソッドを呼び出す
コントローラにレコードの更新処理をするupdateメソッドを追加
findメソッドで特定したレコードに対してupdateメソッドを実行しています。
1 2 3 4 5 6 7 8 9 10 11 |
public function update(Request $request) { Member::find($request->id)->update([ 'name' => $request->name, 'age' => $request->age, 'mail' => $request->mail, ]); //登録処理後、一覧画面に遷移する return redirect('/member'); } |
更新後は、初期画面の一覧に遷移します。
データが正しく更新されているか確認してください。
登録レコードの削除【Delete】
では最後に削除機能を実装しましょう。
レコード編集用のフォームレイアウトに追記(blade)
削除機能用のアンカーリンクを編集用のフォームに追加しましょう
追加する場所はformの閉じタグの下です(formタグ内に記述すると正常に動きません)。
resources/views/edit.blade.php
1 2 3 4 5 6 7 8 9 10 11 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>入力フォーム</title> </head> <body> 登録番号:{{ $member->id }} <a href="/member/delete/{{ $member->id }}">このレコードを削除する</a> |
削除処理用のルーティングを追加
編集フォームの画面表示と同様にルートパラメータを設定します。
1 |
Route::get('/member/delete/{id}', [App\Http\Controllers\MemberController::class, 'delete']); |
コントローラにdeleteメソッドを追加
データベースのmemberテーブルからアンカータグでクリックされた登録番号のレコード情報に対して削除処理を実行します。
1 2 3 4 5 |
public function delete(Request $request) { Member::find($request->id)->delete(); return redirect('/member'); } |
削除処理実行後は、初期画面の一覧に遷移します。
レコードは、削除されているか確認してください。