🍊

Laravelを使ってAjax通信を理解する

2024/06/05に公開

1. Ajax通信とは

非同期通信です。
リクエストを送った後に、サーバーからのレスポンスを待たずに(またはサーバーを意識せずに)、ユーザーは他の作業をすることができます。

Ajax(Asyncronous JavaScript + XML)
XML - タグに独自の意味づけができるマークアップ言語
JavaScriptを用いて、XML形式のファイルを作り、非同期処理を行うという技術です

例えば、ユーザーは、フォームを提出した後、画面をリロードさせずに結果を見ることができます。

2. 今回作るもの

献立のメニューを入力して、結果を表示するといういたってシンプルなものです。

3. まず準備

1. Laravelの環境構築

こちらのサイトを参考にしました。
https://grune.co.jp/blog/laravel-create-local-environment/

2.データベース

今回、簡単なプロジェクトなので、サーバーを使わないsqliteを使用します。以下のサイトを参考にしました。
https://note.com/flogcode/n/n171bc5981a32

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