2018/10/12
WEBアプリの基本機能をCRUD(クラッド)といいます。
C・・・Create (新規作成)
R・・・Read (一覧表示)
U・・・Update (更新)
D・・・Delete (削除)
前回は上の例でいくとCreateをやりました。
今回はUpdateの処理をやります。
編集画面のフロー
編集画面の主なフローは以下になります。
1. [View] リストごとに編集ページへのリンクをかける&レコードのidをパラメータにする
2. [routes] コントローラにとばす
3. [Controller] idを条件にしてレコードを抽出⇒Viewに連想配列で渡す
4. [View] inputタグのvalue属性にカラムの値を入れる
5. [routes] コントローラにとばす
6. [Controller] Eloquentでレコードの保存⇒HOME画面へリダイレクト
7. [View] HOME画面
ポイントはidを条件にしてレコードを抽出&保存するところですね。
これはモデルクラスのfindメソッドを使います。
モデル::find(主キー);
findOrFailメソッドを使うと検索結果が無い場合でもModelNotFoundException をスルーします。
findメソッドよりこちらを主に使います。
patchメソッドについて
編集フォームから値を送信するHTTPメソッドはpatchメソッドを利用します。
編集画面にはpatchメソッドを入れるわけですが、HTMLはpatchメソッドをサポートしていません。
この場合、隠しフィールドとしてフォームに追加します。
<input type="hidden" name="_method" value="PATCH">
ルーティングの設定でもHTTPはpatchを指定します。
Route::patch(' url ', ' コントローラ@メソッド ');
チュートリアル
以前作成した簡易フォームに編集画面を追加します。
実現したいこと
- 編集画面の作成
- UPDATEの処理
手順
1. 編集のページへのリンクを作成
前回一覧ページ(all.blade.php)を作成しましたが、そこに編集ボタンを追加します。
Bootstrapのtableクラスを利用してデザインを少し整形しました。
{{-- 子テンプレート --}} {{-- resources/all.blade.php --}} @extends('layouts.master') @section('title', '入力した内容を表示するサンプルページ') @section('content') <p>{{$message}}</p> <!-- ↓↓↓ 今回記述した箇所 ↓↓↓ --> <table class="table table-striped"> <!-- loop --> @foreach($data as $val) <tr> <td>{{$val->id}}</td> <td>{{$val->onamae}} さん</td> <td><a href="/mylaravel/public/greeting/edit/{{$val->id}}" class="btn btn-primary btn-sm">編集</a></td> </tr> @endforeach </table> <!-- ↑↑↑ 今回記述した箇所 ↑↑↑ --> @endsection
2. ルーティングの設定
編集ボタンを押したときの処理を routes.php に記述します。
Route::get('/greeting/edit/{id}', 'GreetingController@edit');
上記の記述で
http://localhost/mylaravel/public/greeting/edit/[パラメータ]
にアクセスしたら
Greetingコントローラのeditメソッドが実行されるようになります。
3. コントローラにeditメソッドを追記
#app/Http/Controllers/GreetingController.php : #greeting/editにアクセスされた場合 public function edit($id) { #レコードをidで指定 $data = Greeting::findOrFail($id); #viewに連想配列を渡す return view('edit',['message' => '編集フォーム','data' => $data]); } :
4. 編集フォームの作成
入力フォーム(index.blade.php)をコピーして、それをカスタマイズして編集フォーム(edit.blade.php)にします。
{{-- 子テンプレート --}} {{-- resources/edit.blade.php --}} @extends('layouts.master') @section('title', '入力した内容を表示するサンプルページ') @section('content') <p>{{$message}}</p> <form class="form-signin" role="form" method="post" action="/mylaravel/public/greeting/update/{{$data->id}}"> <input type="hidden" name="_token" value="{{csrf_token()}}"> {{-- 隠しフィールド --}} <input type="hidden" name="_method" value="PATCH"> <input type="text" name="onamae" value="{{ $data->onamae }}" class="form-control" placeholder="名前を文字を入力してください" autofocus> {{-- バリデーション --}} @if($errors->has('onamae')) <p class="text-danger" style="margin-bottom: 30px;">{{ $errors->first('onamae') }}</p> @endif <button class="btn btn-lg btn-primary btn-block" type="submit">送信</button> </form> @endsection
5. ルーティングの設定&コントローラにupdateメソッド追加
編集フォームの送信メソッドはpatchなのでルーティングは以下のようになります。
#app/Http/routes.php : # 編集フォーム⇒UPDATE処理 Route::patch('greeting/update/{id}', 'GreetingController@update'); :
次にGreetingControllerにupdateメソッドを追加します。
#app/Http/Controllers/GreetingController.php : #DBの更新処理 public function update(Request $request,$id) { $greeting = Greeting::findOrFail($id); $greeting->onamae = $request->input('onamae'); $greeting->save(); #return redirect('greeting',['status' => 'UPDATE完了!']); ←error! return redirect('greeting')->with('status', 'UPDATE完了!'); }
上のコードを少し解説します。
return redirect('greeting')->with('status', 'UPDATE完了!');
DBの更新処理をしたあとに greeting.blade.php へリダイレクトさせます。
リダイレクト時にFlashメッセージを指定します。
6. greeting.blade.phpにFlashメッセージを表示
リダイレクト先のページでFlashメッセージを表示させます。
@if (session('status'))<div class="alert alert-success" role="alert" onclick="this.classList.add('hidden')">{{ session('status') }}</div>@endif
onclick="this.classList.add('hidden')" でクリックすると非表示になるように指定します。
全体のソースは以下になります。
{{-- 子テンプレート --}} {{-- resources/greeting.blade.php --}} @extends('layouts.master') @section('title', '入力した内容を表示するサンプルページ') @section('content') {{-- ↓↓↓ 今回記述した箇所 ↓↓↓ --}} @if (session('status'))<div class="alert alert-success" role="alert" onclick="this.classList.add('hidden')">{{ session('status') }}</div>@endif {{-- ↑↑↑ 今回記述した箇所 ↑↑↑ --}} <p>{{$message}}</p> <form class="form-signin" role="form" method="post" action="/mylaravel/public/greeting"> <input type="hidden" name="_token" value="{{csrf_token()}}"> <input type="text" name="onamae" class="form-control" placeholder="名前を文字を入力してください" autofocus> {{-- バリデーション --}} @if($errors->has('onamae')) <p class="text-danger" style="margin-bottom: 30px;">{{ $errors->first('onamae') }}</p> @endif <button class="btn btn-lg btn-primary btn-block" type="submit">送信</button> </form> @endsection
4. 動作確認
WEBサーバを起動して下記のURLにアクセス。
http://localhost/mylaravel/public/greeting/all
はじめて入力した laravel の文字を更新してみます。
"laravelさん"の文字の横にある編集ボタンをクリック。
laravelの文字を削除してCodeigniterと入力しました。
送信ボタンを押すと無事に"UPDATE完了!"というFlashメッセージが表示されました。
Flashメッセージをクリックすると
onclick="this.classList.add('hidden')"
が働いて消えます。
"一覧表示" のメニューをクリックしてみるとlaravelがCodeigniterにきちんと更新されているのが確認できました。
はまったところ
redirect処理
テンプレートに値を渡す場合は
view( テンプレート , 連想配列 );
と、viewメソッドの第2引数に連想配列を指定していました。
redirectメソッドも同じような感じで以下のように記述しました。
return redirect('greeting',['status' => 'UPDATE完了!']);
これはエラーになります。
redirectメソッドで値を渡す場合はwithを使います。
return redirect('greeting')->with('status', 'UPDATE完了!');
この記述でエラーが消えました。
新しいページヘリダイレクトした後、保存したメッセージ(status)を表示する方法は
@if (session('status')) <div class="alert alert-success"> {{ session('status') }} </div> @endif
この記述でOKです。
"alert alert-success" というCSSのクラスはBootstrapで用意されているCSSのクラスになります。
仕事で Laravel を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら。