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 を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら。