Laravelを使ってAjax通信を理解する
1. Ajax通信とは
非同期通信です。
リクエストを送った後に、サーバーからのレスポンスを待たずに(またはサーバーを意識せずに)、ユーザーは他の作業をすることができます。
Ajax(Asyncronous JavaScript + XML)
XML - タグに独自の意味づけができるマークアップ言語
JavaScriptを用いて、XML形式のファイルを作り、非同期処理を行うという技術です
例えば、ユーザーは、フォームを提出した後、画面をリロードさせずに結果を見ることができます。
2. 今回作るもの
献立のメニューを入力して、結果を表示するといういたってシンプルなものです。
3. まず準備
1. Laravelの環境構築
こちらのサイトを参考にしました。
2.データベース
今回、簡単なプロジェクトなので、サーバーを使わないsqliteを使用します。以下のサイトを参考にしました。
3.マイグレーションファイルを作成
php artisan make:migration create_menus_table --create=menus
マイグレーションファイルを編集します
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('menus', function (Blueprint $table) {
$table->id();
$table->string('staple');
$table->string('main');
$table->string('sub');
$table->string('soup');
$table->string('drink');
$table->string('dessert');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('menus');
}
};
マイグレートします
php artisan migrate
4.モデルの作成
まずモデルを作ります
php artisan make:model Menu
モデルを設計します
class Menu extends Model
{
use HasFactory;
protected $fillable = [
'staple', 'main', 'sub', 'soup', 'drink', 'dessert'
];
}
5.コントローラの作成
コントローラを作ります
php artisan make:controller MenuController
6.ルート作成
元々view('welcome')となっていたところを、view('menu')しました。
//routes/web.php
Route::get('/menu', function () {
return view('menu');
});
7.UI作成
welcome.blade.phpの名前をmenu.blade.phpにして、cssなどもろもろ消して、書き換えました。
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Menu</title>
</head>
<body class="antialiased">
<div>
<h1>献立作成</h1>
<br>
<br>
<form>
@csrf
主食:<br>
<input name="staple">
<br>
主菜:<br>
<input name="main">
<br>
副菜:<br>
<input name="sub">
<br>
汁物:<br>
<input name="soup">
<br>
飲み物:<br>
<input name="drink">
<br>
デザート:<br>
<input name="dessert">
<br>
//submitボタンにidを付与する
<button type="button" id="create">作成</button>
</form>
</div>
<div class="menus">
//ここにAjax通信で受け取った結果のHTMLが入る
</div>
</body>
</html>
4.いよいよAjax通信の実装
1. ajaxを使うために
1. jQueryが使えるようにする
ajax通信は、jQueryのプラグイン(拡張機能)です。
jQueryとは、JavaScriptを簡単に記述できるようにするためのライブラリです。
LaravelでjQueryの機能を使用できるようにするためには、以下のタグを<head>タグ内または<body>タグの最後に追加する必要があります。
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
2. csrf_token
JacaScriptで駆動するアプリケーションを構築する場合、JavaScript HTTPライブラリーに対し、全ての送信リクエストへCSRFトークンを自動的に追加させると便利です。
laravel公式ページ⇩
https://readouble.com/laravel/5.5/ja/csrf.html
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
//metaタグを追加
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Menu</title>
</head>
2. 処理の流れ
jQueryを使用してAjax通信を行い、献立データをサーバーに送信して、レスポンスを受け取り、ページに表示するための処理を行うよう書いていきます。
① Formをsubmitする (= ID属性が"create"の要素がクリックされる)
② Ajax通信が開始され、データがサーバーに送信される
③ サーバー(コントローラ)でデータが処理され、レスポンスが生成される
④ Ajax通信が完了し、レスポンスが受け取られる
⑤ レスポンスに基づいて、HTMLが生成され、ページに追加される
⑥ Ajax通信が失敗した時の処理を書きます
ここで重要なことは、②〜④のステップが非同期で行われるということです。
つまり、②〜④が行われている間でもユーザーは同じ画面で違う作業をすることができます。
ブラウザのページが更新されずに結果が返されるため、ユーザーはサーバーとのやり取りを意識することなく作業を続けられるわけです。
そういう意味で、「レスポンスを待たずに次の処理をできる」という特徴があると理解しました。
3. 実際のコード
//menu.blade.php
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(function() {
// ① Formをsubmitする (= ID属性が"create"の要素がクリックされる)
$("#create").click(function() {
// ② Ajax通信が開始され、データがサーバーに送信される
$.ajax({
type: "POST",
url: "/postmenu",
dataType: "json",
data: {
"_token": "{{ csrf_token() }}",
staple: $("input[name='staple']").val(),
main: $("input[name='main']").val(),
sub: $("input[name='sub']").val(),
soup: $("input[name='soup']").val(),
drink: $("input[name='drink']").val(),
dessert: $("input[name='dessert']").val(),
},
})
// ④ Ajax通信が完了し、レスポンスが受け取られる
.done(function(res) {
console.log(res);
// ⑤ レスポンスに基づいて、HTMLが生成され、ページに追加される
var html = `<div>
<h1>献立一覧</h1>
<br>
<h2>主食</h2>
<h3>${res.staple}</h3>
<br>
<h2>主菜</h2>
<h3>${res.main}</h3>
<br>
<h2>副菜</h2>
<h3>${res.sub}</h3>
<br>
<h2>汁物</h2>
<h3>${res.soup}</h3>
<br>
<h2>飲み物</h2>
<h3>${res.drink}</h3>
<br>
<h2>デザート</h2>
<h3>${res.dessert}</h3>
</div>`;
$('.menus').append(html);
})
// ⑥ Ajax通信が失敗した時の処理を書きます
.fail(function(jqXHR, textStatus, errorThrown) {
console.error("Ajax request failed:", textStatus, errorThrown);
alert("献立の作成に失敗しました。");
});
});
});
</script>
//MenuController.php
// ③ サーバー(コントローラ)でデータが処理され、レスポンスが生成される
public function postMenu(Request $request)
{
$menu = new Menu();
$menu->staple = $request->input('staple');
$menu->main = $request->input('main');
$menu->sub = $request->input('sub');
$menu->soup = $request->input('soup');
$menu->drink = $request->input('drink');
$menu->dessert = $request->input('dessert');
$menu->save();
return response()->json($menu);
}
ルートの設定
ajax通信が、サーバー(コントローラー)にアクセスできるようにURLを指定しておきます。今回入力されたデータをデータベースに保存するので、リクエストパラメータをpostにします。
//web.php
Route::post('/postmenu', [MenuController::class, 'postMenu']);
5. まとめ
Ajax通信はJavaScriptを用いて、サーバーにリクエストを送る。
サーバーからのレスポンスを受け取った後に、
ページの一部を更新することができます。
これによりページ全体の再読み込みを行わなくていい。
また、サーバーでの処理が行われている間も
ユーザーはブラウザでサーバーを意識せずに作業を続けることができる。
Discussion