laravel

Laravel8でjQueryを使ってAjax通信を行う方法【405エラーと419エラーの対処法も合わせて紹介】

2021年8月28日

jqueryのコード

 

あなた
Laravel8系でjQueryを使ってajax通信を行いたいのですがうまくいきません。

どうしたらいいでしょうか?

 

こんな疑問に答えていきます。

なお、今回は主に「LaravelでjQueryを使ってPOST(DELETE)の通信を行う」ことをテーマに解説していきます。

 

【前提】

・Laravel8系

・jQuery 3.6

 

※なお、まだjQueryを導入できていない方はLaravelでjavascript、jQueryを使う方法を参考に、導入してください。

プログラミング言語
Laravelでjavascript、jQueryを使う方法

  あなたlaravelでjavascriptやjqueryを使うにはどうしたらいいのだろうか   今回は上記のような疑問を抱えている方に向けて、Laravelでjavascrip ...

続きを見る

 

Laravel8でjQueryを使ってAjax通信を行う方法

 

今回行いたい挙動は、以下だとします。

 

・削除ボタンを押したらajax通信で非同期で削除を行う

・削除処理の成功失敗に応じて、フラッシュメッセージを表示する

 

ファイルの構成は以下のとおりです。

 

App
//コントローラー
- Http
-- Controllers
--- Api
---- Admin
----- DeleteUserController.php

//js
- resources
-- js
--- deleteconfirm.js

//サービス
- Http
-- Services
--- UserService.php

//ルーティング
- routes
-- user.php

//ビュー
- resources
-- views
--- admin
---- users
----- index.blade.php

 

では、jsと、phpの各ファイルの中身を解説していきます。

 

js(jQuery)側

 

js(jquery側)のコードは以下のような感じになります。

ちなみに、「delete_button_10」というようなid属性を持ったボタンをクリックした時に処理が走るようにします。

(後ほど、view側のコードも紹介します。)

 

$( function ()
{
    $( "[id^=delete_button]" ).on( "click", function ()
    {
        const id = $( this ).attr( "id" ).substr( 14 );//delete_button_IDのIDだけ切り出す
        console.log( id );
        //csrf対策
        $.ajaxSetup( {
            headers: {
                'X-CSRF-TOKEN': $( 'meta[name="csrf-token"]' ).attr( 'content' )
            }
        } );
        if ( confirm( '本当に削除してもいいですか?' ) )
        {
            $.ajax( {
                type: "post", //形式
                url: `/admin/users/api/delete/${ id }`, //リクエストURL
                dataType: 'json',
                data: { "id": id, "_method": "DELETE" } //deleteメソッドを追加
            } )
                //成功時の処理
                .done( ( res ) =>
                {
                    if ( res[ "status" ] == "success" )
                    {
                                                //view側の削除したいHTML要素のidは「row_数字(ID)」とする
                        $( `#row_${ id }` ).remove();
                        flashMessage( id, res[ "status" ], res[ "message" ] );
                    }

                } )
                                //失敗時の処理
                .fail( function ( jqXHR, textStatus, errorThrown )
                {
                    console.log( jqXHR );
                    console.log( textStatus );
                    console.log( errorThrown );
                    flashMessage( id, 'error', '削除に失敗しました。' );
                } );
        }
    } );
    /**
     * 処理終了時にフラッシュメッセージを表示
     * @param {int} id
     * @param {str} status
     * @param {str} message
     */
    function flashMessage ( id, status, message )
    {
        let bgColor = 'bg-red-300';
        let dom = `<div id ="flash_${ id }" class="${ bgColor } w-1/2 mx-auto mb-4 p-2 text-white">
           ${ message }
        </div>`;
        if ( status == "error" )
        {
            $( ".container" ).append( dom );
        } else
        {
            bgColor = 'bg-blue-300';
            dom = `<div id ="flash_${ id }" class="${ bgColor } w-1/2 mx-auto mb-4 p-2 text-white">
           ${ message }
        </div>`;
            $( ".container" ).append( dom );
        }
        //2秒後に消す
        setTimeout( function ()
        {
            $( `#flash_${ id }` ).remove();
        }, 2000 );
    }
} )

 

view側のコードは次のようになっています。

 

....省略... 
<meta name="csrf-token" content="{{ csrf_token() }}">
....省略...
<div class="container">
....省略...
<tbody>
    @foreach ($users as $user)
        <tr id="row_{{ $user->id }}">
            <td class="px-4 py-3"> {{ $user->name }}</td>
            <td class="px-4 py-3"> {{ $user->email }}</td>
            <td class="px-4 py-3">{{ $user->created_at }}</td>
            <td class="px-4 py-3">
                <button onclick="location.href='{{ route('admin.users.edit', ['user' => $user->id]) }}'"
                    class="text-white bg-indigo-400 border-0 py-2 px-4 focus:outline-none hover:bg-indigo-500 rounded">編集</button>
            </td>
            <td class="px-4 py-3">
                <button id="delete_button_{{ $user->id }}"
                    class="text-white bg-red-400 border-0 py-2 px-4 focus:outline-none hover:bg-red-500 rounded">削除</button>
            </td>
        </tr>
    @endforeach
</tbody>
....省略...

 

ちなみに、view側には以下のコードは必ず埋め込んでおいてください。

 

 <meta name="csrf-token" content="{{ csrf_token() }}">

 

csrf対策のものです。

こちらがないと通信時に419エラーになります。

 

ajax通信の雛形

 

さきほど紹介したjsファイルの中の以下の部分がajax通信の雛形です。

 

$.ajax( {
         type: "post", //形式
         url: `/admin/users/api/delete/${ id }`, //リクエストURL
         dataType: 'json', //データタイプ
         data: { "id": id, "_method": "DELETE" } //deleteメソッドを追加
  } )

 

削除処理の場合はdataキーに「"_method": "DELETE"」を指定してあげるとうまくいきます。

これがないと「405 (Method Not Allowed)」で怒られます。

 

PHP(laravel)側①ルーティングファイル

 

php側のコードを紹介していきます。

今回は、「ドメイン/admin/users/api/delete/削除対象のユーザID」にリクエストをしたら削除をしたいので、まずはそちらを明示するルーティングファイルを編集します。

コードは以下のとおりです。

 

//API
Route::delete('/users/api/delete/{id}', [DeleteUserController::class, 'delete'])
    ->middleware('auth:admins')
    ->name('users.delete');

 

こちらの記述をすることで、リクエストが来た場合に「DeleteUserController」の「deleteメソッド」が走ることになります。

 

ルーティングファイルの注意点

 

削除処理の場合ルーティングファイルで「Route::delete」としてあげてくださいね。

ここをpostとかにすると「405 (Method Not Allowed)」で怒られます。

削除 → Route::delete

更新 → Route::put

です。

 

PHP(laravel)側②コントローラー

 

次にコントローラー側の記述です。

今回は次のように記述しました。

 

<?php

namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Controller;
use App\Http\Services\UserService;

class DeleteUserController extends Controller
{
    /**
     * @var UserService
     */
    protected $userService;

    public function __construct(UserService $userService)
    {
        $this->middleware('auth:admins');
        $this->userService = $userService;
    }

    public function delete($id)
    {
        //ユーザーの削除を行う
        try {
            $this->userService->delete($id);
            $status = 'success';
            $message = '削除が完了しました。';
            $returnArr = [
                'status' => $status,
                'message' => $message
            ];
            return response()->json($returnArr);
        } catch (\Throwable $th) {
            $status = 'error';
            $message = '削除に失敗しました。';
            $returnArr = [
                'status' => $status,
                'message' => $message
            ];
            return response()->json($returnArr);
        }
    }
}

 

ajax通信で受け取った対象idを、userServiceクラスに渡してあげて、処理を走らせる内容になっています。

注意点は、レスポンスを返す時の形です。

json形式で返してあげないとエラーになります。

「 return response()->json($returnArr);」という記述の部分でjsonで返しています。

 

PHP(laravel)側③サービスクラス

 

最後にサービスクラスです。

コードは次の通り。

 

<?php

namespace App\Http\Services;

use Illuminate\Support\Facades\Hash;
use App\Models\User;
use Illuminate\Support\Carbon;

class UserService
{
    public function __construct()
    {
    }

    /**
     * ユーザー削除
     */
    public function delete($id)
    {
        $user = User::findOrFail($id);
        $user->deleted_at = Carbon::now()->format("Y-m-d H:i:s");
        $user->save();
    }
}

 

今回の自分の実装では、削除は物理削除ではなく、deleted_atに日付を入れるだけとしています。

別に物理削除でも構いません。

delete()のメソッドはお好きにカスタマイズしてみてください。

 

PHP側のコードの紹介、解説は以上になります。

 

Laravel×Ajaxで405エラー、419エラーが出る時の対処法

 

コードの解説時にもいくつか紹介しましたが、LaravelでjQueryを使ったAjax通信を実装する時によく出てくる405エラーと419エラーの解決方法を、それぞれ紹介します。

 

405 (Method Not Allowed)

 

メソッド(post、get、delet、put)が許可されていない場合に起きるエラーです。

このエラーが出た場合は以下を確認してください。

 

・jQuery側 → ajaxのdataキーで「 "_method": "実行したいメソッド"」を記述していること 

・php側 → ルーティングファイルで実行したいメソッドを指定していること(Route::post、Route::deleteなど)

 

419 (unknown status)

 

こちらはcsrfの対策ができていない場合に起きるエラーです。

次のことを確認してください。

 

・jQuery側 → ajax通信の前にheaderにcsrfトークンを設定していること(設定するためのコードはこの記事のコード紹介のところに載せてあります)

・blade.php側 → meta name属性でcsrfの記述。「<meta name="csrf-token" content="{{ csrf_token() }}">」を設定してください。

 

補足:csrfとは

 

補足的に説明です。

csrfとはクロスサイトリクエストフォージェリの略称です。

 

クロスサイトリクエストフォージェリは、認証済みユーザーに代わって不正なコマンドを実行する、悪意のある攻撃の一種です。

 

公式ドキュメントでは上記のように解説されています。

要は「悪意をもった第三者が不正にあなたの情報を利用するための攻撃」だと認識しておけばOKです。

攻撃の細かい仕組みを知りたい方はIPAの公式記事が参考になると思います。

 

ということで今回は、LaravelでjQueryを使ってAjax通信を行う場合の解説でした。

 

プログラミングスクールに関する情報

【無料あり】プログラミングスクールおすすめランキング【WEBエンジニアになりたい方向け】と書かれた画像
【無料あり】プログラミングスクールおすすめランキング【WEBエンジニアになりたい方向け】

  あなたプログラミングスクールに通いたいけどたくさんありすぎてどこがいいのかわかりません。   最近はエンジニアブームということもありプログラミングスクールが増えました。 一方でたくさんありすぎてど ...

続きを見る

返金保証ありのプログラミングスクールランキング【エンジニアが選びました】と表示されたパソコンの画面
【転職保証つき】返金保証ありのプログラミングスクールランキング【エンジニアが選びました】

  あなた返金保証がついているオススメのプログラミングスクールってありますか?   結論から話すと、返金保証つきのプログラミングスクールランキングは次の通りです。   1位:DMMWEBキャンプ  【 ...

続きを見る

wordpress
【無料あり】WEB制作を学べるオンラインスクールランキング【副業で稼ぎたい方向け】

  あなたWeb制作の副業で稼ぎたいけど、どのスクールで学ぶのが良いの? スクール選びで失敗はしたくないです。   ↑このような疑問や不安を解決するべく、現役のWebエンジニアがWEB制作を学べるスク ...

続きを見る

フリーランス
無料あり:フリーランスを目指せるプログラミングスクールランキング【体験をもとに徹底分析しました】

  あなたフリーランスエンジニアを目指すことができるプログラミングスクールってありますか?   最近では、高年収や働きやすさの魅力からフリーランスエンジニアを目指す方も増えてきました。 結論から話すと ...

続きを見る

WEB系自社開発企業にいけるプログラミングスクールランキング【現役エンジニアおすすめ】と書かれた画像
WEB系自社開発企業にいけるプログラミングスクールランキング【現役エンジニアおすすめ】

  あなたWEB系の自社開発企業に就職したいです。 オススメのスクールを教えて下さい。   結論から話すと、WEB系自社開発に行きやすいスクールのランキングは以下の通り。   第1位:テックアカデミー ...

続きを見る

-laravel

© 2024 エンジニアてんし君ブログ