本記事は、具体的なイメージからAjax(非同期)の使い方・通信の流れを理解できる内容になっています。
ajaxが非同期というのはなんとくなく理解したけど、実際にLaravelでどのように使うのかな?
このような悩みが解決できるようになってみます。
具体的にイメージしたほうが、より頭に入りやすいので、このような機能を元に解説します。
Ajaxを使用して項目を追加
表示の名前は、大河ドラマの「どうする家康」を見てる影響です。笑
それはさておき、どのようなことをしているか説明するとID番号を入力して、「いざ出陣ボタン」を押すと、入力したIDに紐づくnameカラムのデータを取得して、中央の下に追加しています。
例えば、ajaxを使わずに、入力したidと紐づく名前を出力しようとすると、出陣ボタン(リクエスト送信)を押したタイミングで、htmlは再度読み込まれ最初に出陣してリストに上がった者は削除されます。
しかし、ajaxを使用すると、htmlを再ロードせずにデータベースからデータを参照して表側の表示を変更できます。
ずばり、これがajaxを使う上でのメリットです!
※正式には、今回のようなシンプルな構成であれば、セッションやキャッシュを利用して実現は可能ですが、今回は考えないようにお願いします。
事前に準備
データベースのデータを参照するので、簡単なデータを用意しておきます。
テーブル名: vassals
※vassalは家臣という意味です。
id | name |
---|---|
1 | 酒井忠次 |
2 | 本多忠勝 |
3 | 井伊直政 |
使用するファイルを作成します。
● index.blade.php
本記事では、ajaxをjqueryで使用します。
jqueryを利用できるように、headタグ内にCDNを利用したjqueryファイルを読込みます。
<head> <script src="https://code.jquery.com/jquery-3.4.1.js"></script> </head>
※jqueryの利用方法は、他にlaravel mixを使ったCDNに依存しない方法があるので、詳しく知りたい場合はお調べ願います。
他のファイルは下記となります。
●web.php
●TestContorroler.php
●Vassal.php
TestController.phpを通して、htmlで表示させる部分の解説は致しませんので、 そちらの基本知識は前提となります。
全体の流れ
それでは、先ずは全体の動作の流れを見ていきます。
blade(html) に設定されたボタンを押す
ボタンを押すとjsのイベントが発動 イベント内に記述されたajaxが動く
ajaxで記述したurlを読みに行く
web.phpで記述している該当のルートを通って、コントローラを読みに行く
コントローラからデータを取得する
jsに値をレスポンスで返す
blade(html)の表示が変わる
文字だけだと、複雑に感じるかもしれないので、ここではなんとなくの理解で大丈夫です。
慣れてしまえばとてもシンプルに感じると思います。
ソースコードの記述はどこからでもよいですが、通信の流れに沿って作成していきます。
ではコードを記述していきます!
bladeファイルに記述
<body> <div class="main"> <h2>いざ出陣!<h2> <ul> <li>徳川 家康</li> </ul> <input type="text" name="id" value="" placeholder="ID番号を入力"> <button class="iza">出陣ボタン</button> </div> </body>
先ずは見た目の部分はこのように記述しています。
特別な記述はなく、普通のhtmlです。
headタグに必要なコードを記述します。
<head> {{-- 他の記述は省略 --}} <meta name="csrf-token" content="{{ csrf_token() }}"> </head>
ajaxリクエストにもCSRFトークンを含める必要があります。
meta name="csrf-token" ...の部分でajaxリクエスト時に利用するCSRFトークンを生成しています。
因みに、もしCSRFトークンを含めずajaxを使用した場合、コンソールログには下記のようにエラーが発生します。
http://localhost/laravel-demo/public/iza 419 (unknown status)
検証のNetworkエラーは下記のように出ます。
"CSRF token mismatch.", exception: "Symfony\Component\HttpKernel\Exception\HttpException",…}
もし上記のようなエラーが発生した場合は、CSRFを疑いましょう。
それでは、ajaxの部分をbodyタグ内の最後に記述します。
<script> $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $("[name='csrf-token']").attr("content") }, }) $('.iza').on('click', function(){ id = $('input[name="id"]').val(); $.ajax({ url: "{{ route('iza') }}", method: "POST", data: { id : id }, dataType: "json", }).done(function(res){ console.log(res); $('ul').append('<li>'+ res + '</li>'); }).faile(function(){ alert('通信の失敗をしました'); }); }); </script>
$.ajaxSetup({...の部分で ajaxリクエスト時にリクエストヘッダーにCSRFトークンを設定します。
CSRFトークンは予めheadタグに記述していたnameがcsrf-tokenのcotentの値を取得して設定します。
$('.iza').on...の部分では、class=izaで記述されているボタンはクリックするとイベントが発火します。
id = $('input[...で入力されているidを取得します。
$.ajax({...からajaxリクエストの部分です。
1行1行見ていきます。
url: "{{ route('iza') }}"で、リクエスト先のurlを記述します。
bladeファイル内に記述しているので、laravelのroute()関数を使用して、ルート名 "iza" に対応するURLを生成しています。
今回は、bladeファイル内に記述してるのでroute()関数が使用できますが、jsファイルに区別して記述する場合もあります。
その場合は、route()関数は使用できないので、別の方法でURLを渡す必要があるので注意してください。
ルート名 "iza" に対応するURLをweb.phpで記述していないので、ページを開くとこの時点でエラーが発生します。
後程、web.phpに記述します。
method: "POST"は、リクエストの送信方法です。
GET、POSTの違いなどはここでは詳しく解説は致しませんが、基本的に敢えてGETを使う必要はないので、特別な仕様でなければPOSTで問題ありません。
data: { id : id }では、キー名をidに指定して、右側で変数idを記述したオブジェクトです。
リクエストで送信するデータをここで設定しています。
dataType: "json"では、サーバーからのレスポンスがどのような形式であるかを指定します。
例えば、もしhtml形式でサーバーからレスポンスを受ける場合は、dataType: "html"とします。
今回は、データのやりとりなのでjson形式でレスポンスを受けるように設定しています。
.done(function(res){....以降で、レスポンスを受けた後の処理となるので、後ほど解説いたします。
それでは、次にリクエスト先のルートをweb.phpに記述します。
web.phpに記述
先ほど、ルート名 "iza" に対応するURLをajax内に設定したので下記のように記述します。
Route::post('/iza', 'TestController@iza')->name('iza');
特にajaxだからといって、特別な記述はありません。
注意なのは、ajax内のmethodにRouteのメソッドを一致しないとエラーとなります。
今回、POSTで設定しているので、Route::postとしています。
TestControllerのiza()メソッドを設定したので、次にTestControllerにiza()メソッドを記述していきます。
TestControllerに記述
記述内容は下記の通りとなります。
public function iza() { $id = request()->get('id'); $name = Vassal::find($id)->name; return response()->json(['name' => $name]); }
ajaxでリクエストのデータをidがキーとして送信しているので、 request()->get()で引数にキー名を記述で、入力された値を取得しています。
Modelから該当のidレコードのnameカラムの値を取得しています。
ここまでは、普段のlaravelの書き方と変わりありません。
最後にreturn でレスポンスとしてjsonを渡す記述をします。
json()メソッドには、js側に渡したい値をキー名をセットして連想配列を渡します。
実は、return ['name' => $name];という記述だけでもJSON形式でレスポンスされます。
個人的には、誰が見てもわかる様にrespose()の方法が良いと思いますが、どちらでも構いません。
ではレスポンスを返したので、もう一度bladeに戻ります。
$.ajax({ url: "{{ route('iza') }}", method: "POST", data: { id : id }, dataType: "json", }).done(function(res){ $('ul').append('<li>'+ res.name + '</li>'); }).fail(function(){ alert('通信の失敗をしました'); }); });
Controllerからレスポンスされると、doneの部分に戻ります。
再度戻ってくるところが、最初はややこしく感じる部分だと思います。
done()メソッドのコールバック関数の引数に返却されたデータが渡されます。
resにコントローラーで渡した連想配列がオブジェクトとして入っています。
なので、res.nameとすると、nameキーの値が取得できます。
あとは、$('ul')...でappendメソッドでnameが入ったliタグを埋め込めば完成です。
最後に.fail(function(){...では、もしajax通信中に障害が起きて通信が途切れた時の処理を記述しています。
シンプルですが参考までに適用しているcssも載せておきます。
style.css
body { display: flex; justify-content: center; align-items: center; height: 100vh; }
お疲れ様です。
いかがでしたでしょうか?
とてもシンプルな作りではありますが、基本を抑えることはとても大事だと感じます。
最新の記事を公開する際には、X(旧Twitter)でもお知らせしています。
ご興味のある方は、ぜひこちらから
フォローをお願いいたします!