2018/10/12
前回でBladeによるテンプレートの継承について学びました。
次に覚えるべき内容はユーザからの入力ですね。
Laravelで入力フォームを作って、入力された内容を表示してみます。
その際、バックエンドではどのようなフローになるでしょうか?
今回はLaravelのリクエスト処理について学びます。
リクエスト処理の流れ
入力されたデータがどのような流れになるのか大まかに追ってみます。
まず、フォームで入力された内容をコントローラへ渡します。
<form method="post" action="/test"> <input type="text" name="str"> :
コントローラーのメソッドは、アクセスするアドレスによって決定されます。
/test/indexへのポスト送信の処理は、postIndexのメソッドが処理をします。
TestControllerにpostIndexメソッドを追加します。
次にpostindexメソッドにフォームのデータを受け取る処理を書きます。
Requestクラスのinputメソッドでフォームからの入力内容を受け取ることができます。
#入力されてデータを変数に代入 $res = $request->input('str');
view関数の第2引数では連想配列の形式でViewに変数を渡すことができます。
return view('View名', ['message' => $res]);
View画面でControllerで設定した変数を表示します。
<?php echo $message; ?>
これが大まかな流れになります。
CSRF対策
CSRFとはクロスサイトリクエストフォージェリの略で(シーサーフ)と呼びます。
CSRFはWebアプリケーションの脆弱性をついた攻撃手法です。
まず、攻撃者はウェブページやメールに罠をしかけたリンクを設置します。
もしそのリンクにアクセスした場合、知らないうちに別のサイトへ書き込みを行わせます。
パソコン遠隔操作事件では、このCSRFの攻撃手法が使われました。
CSRFの対策はフォームから送られるトークンをサーバで照合させるような仕組みを作れば回避できます。
Laravel5.2ではCSRF対策がとられています。
HTML Form に設定する時は以下の方法で実装します。
<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
Laravel5.2でフォームを作成する場合、このCSRFのトークンを送らないとエラーになりますので注意してください。
チュートリアル
実現したいこと
今回のチュートリアルでは入力したデータを表示するページを作成します。
これまでの復習をかねて、Bootstrapを使ってBladeの継承を利用して親テンプレートと子テンプレートに分割します。
- Bootstrapを使って入力フォームを作成 (※参照:Laravel5.2にBootstrapを組み込む)
- Bladeを使って親テンプレートと子テンプレートを分ける (※参照:Bladeのテンプレートを分割する)
- 入力したデータを表示させる
手順
1. 親テンプレートの作成
{{-- 親テンプレート --}} {{-- resources/views/layouts/master.blade.php --}} <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <!-- InternetExplorerのブラウザではバージョンによって崩れることがあるので、互換表示をさせないために設定するmetaタグです。 --> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- レスポンシブWebデザインを使うために必要なmetaタグです。 --> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>@yield('title')</title> <!-- コンパイルして圧縮されたCSS --> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"> <!-- オプションのテーマ --> <style> body { padding-top: 40px; padding-bottom: 40px; background-color: #eee; } .form-signin { max-width: 330px; padding: 15px; margin: 0 auto; } .form-signin .form-signin-heading, .form-signin .checkbox { margin-bottom: 10px; } .form-signin .form-control { position: relative; height: auto; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: 10px; font-size: 16px; } .form-signin .form-control:focus { z-index: 2; } .form-signin input[type="text"] { margin-bottom: 10px; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } </style> </head> <body> <div class="container"> <h2>@yield('title')</h2> @yield('content') </div> <!-- /container --> <!-- jQuery読み込み --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <!-- BootstrapのJS読み込み --> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> </body> </html>
2. 子テンプレートの作成
{{-- 子テンプレート --}} {{-- resources/greeting.blade.php --}} @extends('layouts.master') @section('title', '入力した内容を表示するサンプルページ') @section('content') {{$message}} <form class="form-signin" role="form" method="post" action="greeting"> {{-- CSRF対策 --}} <input type="hidden" name="_token" value="{{csrf_token()}}"> <input type="text" name="onamae" class="form-control" placeholder="名前を文字を入力してください" required autofocus> <button class="btn btn-lg btn-primary btn-block" type="submit">送信</button> </form> @endsection
3.Controllerでリクエスト処理
XAMPPで開発している方はコマンドプロンプトを起動してArtisanコマンドでControllerを作成します。
Controllerの名前はアッパーキャメルにします。
Modelを利用する場合は複数形の名前(GreetingsController)にします。
ただ、Modelを利用しない場合は、必ずしも複数系にする必要はありません。
今回は単数形の名前に命名します。
php artisan make:controller GreetingController
Artisanコマンドで自動生成されたControllerにgetIndexメソッドとpostIndexメソッドを追加します。
<?php # app/Http/Controllers/GreetingController.php : (※省略) class GreetingController extends Controller { #getでgreeting/indexにアクセスした時の処理 public function getIndex() { return view('greeting', ['message' => 'あなたの名前を入力してください。']); } #postでgreeting/indexにアクセスしたときの処理 public function postIndex(Request $request) { $res = "こんにちは!" . $request->input('onamae')."さん!!"; return view('greeting', ['message' => $res]); } }
この「getIndex」というメソッドは、GETアクセスで「index」というアドレスにアクセスした際に呼び出されるメソッドであることを示します。
このGreetingController自体が/greetingに割り当てられていますから、/greeting/indexにアクセスすると、getIndexが呼び出される、ということになります。
同じ理屈で/greeting/indexにPOST送信するとpostIndexが呼び出されます。
4. ルーティングの設定
ルーティングの設定で、HTTPメソッドへのアクセスをコントローラーに割り当てて処理するときには
Route::HTTPメソッド('アドレス', 'コントローラ名@メソッド名');
と記述していました。
今回のチュートリアルでいくと
Route::get('/greeting', 'GreetingController@getIndex'); Route::post('/greeting', 'GreetingController@postIndex');
ただ、この記述が本当に正しいのか自信はありません。(※一応問題なく動いています。)
5. ブラウザで確認
WEBサーバを立ち上げて以下のアドレスにアクセスします。
http://localhost/mylaravel/public/greeting
"mylaravel" はLaravelのプロジェクト名でしたね。
下のような画面になれば第一フェーズはクリアです。
フォームに文字を入力して下のような画面になれば第二フェーズもクリアです。
”Laravel” と入力してみました。
お疲れさまでした。
注意事項
コントローラに処理を渡すやり方で controllerルーティング というものがあります。
Route::controller( アドレス , コントローラー名 );
しかしこの記述は5.2からは非推奨になっています。
5.3からはなくなる方向です。
使用しないようにしましょう。
仕事で Laravel を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら。