AjaxのPOST処理に認可処理を追加/Policy/Laravel

LaravelでAjax POST処理のPolicyを作っていきます。今回は、Ajaxの詳細には触れていきません。

Userが、AjaxでCommentの編集をすることを想定した流れとなっています。

①:Policy作成の流れ

①-1:Policyの作成

$ php artisan make:policy CommentPolicy

App\Policiesの配下にCommentPolicy.php が作成される。

①-2:Policyを登録

App\Providers\AuthServiceProvider

protected $policies = []に 作成したPolicyを登録

    protected $policies = [
        Comment::class => CommentPolicy::class,
    ];

①-3:Policyのメソッド記述 (True OR Falseを返す)

実際のPolicyの処理を書いていきます。
①-1:Policyの作成 で作成した CommentPolicy.php に処理を記述していきます。

App\Policies\CommentPolicy.php
<?php

namespace App\Policies;

use App\Models\User;
use App\Models\Comment;
use Illuminate\Auth\Access\HandlesAuthorization;

class CommentPolicy
{
    use HandlesAuthorization;

    /**
     * Create a new policy instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    public function update(User $user, Comment $comment)
    {
        return $user->id === $comment->user_id;
    }
}

メソッドの内容としては、非常にシンプルかと思います。

Userのid と commentのuser_idが
・同じ場合はTrueを返し、
・違う場合はFalseを返します。

①-4:Policyの呼び出し

任意のコントローラーにて、①-3:Policyのメソッド記述 で作成したupdateメソッドを呼び出します。
詳細は 「②:AjaxでPolicyを呼び出し/認可」 以降にて記述していきます。

②:AjaxでPolicyを呼び出し/認可

commentの編集をするメソッドに、認可の処理を追加していきます。

CommentController の edit メソッド で実行していきます。

前提として
・ $requestにcomment_idを含めている
・ $requestにinput_textでコメントが含まれている
・ JSに $commentで返す

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

use App\Models\Comment;
use App\Models\User;

class CommentController extends Controller
{

    public function edit(Request $request)
    {

        // comment_idから編集予定のComment modelを取得
        $comment = Comment::where('id', $request->comment_id)->get()->first();

        // 編集処理をするUserの取得    
        $user = Auth::user();

        // 編集User と 編集予定のCommentを作成したUserが 同一なのかを認可
        if($user->can('update',$comment)){

            $comment->comment = $request->input_text;
            $comment->save();

            // JSに$commentを返す。  
            return $comment;
        } else {
            abort(403);
        }
    }

}

③:Ajaxの処理で躓いたところ

正直、上記の処理は、Ajax関係なくない??と思うかと思います。
確かに、上記の処理であれば、Ajax関係ない処理として通用します。

私は、authorize() メソッドを利用した際に躓きました。
authorizeメソッドでは、 Userのインスタンスを渡す必要が無く、自動的に読み込んでくれています。

ここが、AjaxだとUserインスタンスが自動で読み込まれません。

Ajaxの通信でパラメーターデータの送受信する方法 | Laravel / jQuery

jQueryを利用したAjaxの通信でデータの送受信方法を解説していきます。

Laravelにて処理しています。
今回は、LaravelでjQueryを利用する方法などは省略しております。パラメーターデータを送受信する方法に限定しております。また、LaravelでのAjax×jQury処理の全貌をまとめたいと思います。

方法としては1パターンあります。

①:URLに含める
②:Requestに含める

今回は、②:Requestに含める で進めたいと思います。

データ送信 / 受信

$.ajaxのパラメータのdataを利用していきます。

①:Ajaxの処理

今回のポイントはdataパラメーターです。

①-1://–①

・idがedit_commentを含む要素をクリックされた際にイベント発火します。

①-2://–②

・HTMLでdata-id=”XXXX” のXXXXの情報を取得します。 ※後述

①-3://–③

comment_id という名目で、 comment_id //–② のデータを送信します。 $request->comment_id でデータ取得します。  ※後述

$( function ()
{
    $(document).on('click', '[id^=edit_comment]', function(){ //--①

        var comment_id =  $(this).data('id'); //--②
        
        $.ajax({
            type: "get",
            url: "/comment/get",
            data : {
                comment_id:comment_id, //--③
            },
            cache: false,
            dataType: 'json',
        })
        .done((res)=>{
                 console.log( res ); //--成功した時
          })
        .fail((error)=>{
                 console.log( error ); //--失敗した時
          });
    });
})

②:Laravelのルーティング処理

①-1でクリックした際に発火したAjaxイベントに対してルーティング処理してくれる部分です。

url: “/comment/get”, なので、Route::get(‘/comment/get’ でgetで処理します。

web.php
Route::get('/comment/get', [CommentController::class, 'commentget'])->name('comment.get');

③:Contoroller / Ajaxからデータ受信

ルーティング処理で呼び出された、CommenntControllerのcommentgetで処理を書いていきます。

CommentController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\Comment;

class CommentController extends Controller
{
    public function commentget(Request $request)
    {
        $comment_id = $request->comment_id; // --①
        $comment = Comment::where('id', $comment_id)->get()->get();
        return $comment; // --②
    }
}

③-1://–①

①-1://–① で設定したcomment_idのデータを受け取ります。
・$request->comment_id

③-2://–②

retuen で $coomentを Ajaxに返します。

問題なく処理出来ていれば、下記の部分でconsoleに$commentが出力されます。

        .done((res)=>{
               console.log( res ); //--成功した時
})