Laravelで削除の非同期処理を実装する条件
- jQueryを動かすためのCDN
- POST通信をするためのトークン【とても重要】
- HTMLタグから情報を取得するカスタムデータ属性
- コントローラへ非同期通信するためのAjax
- コントローラーへ移動するルーティング
- データを受取りレコードを削除するコントローラー
jQueryを動かすためのCDN
非同期処理(ajax通信)を実装するためにはjQueryの$.ajaxメソッド
が必要です
そのためjQueryを動かすためにCDNをHTMLのheadタグ
に記述します
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@yield('title')</title>
<!--Bootstrap CSS -->
{{--<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">--}}
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
<!--Font Awesome5-->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<script src="https://code.jquery.com/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>
<meta name="csrf-token" content="{{ csrf_token() }}">
</head>
<body class="d-flex flex-column">
<!-- ヘッダー -->
@include('layouts.header')
<!-- コンテンツ -->
@yield('content')
</body>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" ></script>
</body>
</html>
CDNのリンク記述場所に注意
CDNのリンクは、jQueryの処理コード部分よりも
前に記述する必要があります。
後に記述された場合、jQueryが利用できません。
そのため、HTMLのheadタグ内部に記述することが推奨されます。
CDNでの導入方法
https://code.jquery.com にアクセスし
jQuery Core 3.*.*
のminified
をクリック
表示されたscript
のコードをコピーしHTMLへ貼り付けします
POST通信をするためのトークン【とても重要】
LaravelでPOST通信をするには必ずトークンを送る
ための記述が必要です
Laravelの仕様でトークンを送らなければエラーが発生し、
通信が失敗、つまりエラーが発生します。
ajaxでトークンを送信する方法とは?
ajaxのコードを処理を記述するscriptタグへ
非同期処理とセットで以下の記述をすることにより
トークンが送信されます
<script>
// ここからトークン送信処理
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
}
});
//ここから非同期処理の記述
// $(function() {
// $.ajax({
// type: 'POST'
// , url: '/destroy/'+userID
// , dataType: 'json'
// , data: {'id':userID},
ajaxの場合はページを更新しないためエラーコードが出ず
問題には非常に気が付きにくいことが挙げられます
HTMLタグから情報を取得するカスタムデータ属性
削除の対象になるHTMLタグにカスタムデータ属性
で
jQuery側にてHTMLの値
を取得することができます
カスタムデータ属性とは?
htmlタグに付与できるclass属性やid属性などと同じ利用方法の属性で
かつ、オリジナルの名前で設定できる属性
です
カスタムデータ属性は、data-***
で作成します。
***の部分を任意の文字列で設定できます。
他の要素名(class名、ID名など)とは重複できません。
<form class="id">
<input data-user_id="{{$user->id}}" type="submit" class="btn-dell" value="削除">
</form>
削除したいレコードの"ID"をjQueryへ渡すには?
まずはMVCの流れで
コントローラーでモデル(データベース)の情報を取得します
前提条件
- Laravelのプロジェクトへすでにモデル、コントローラー、ビューファイルが存在する
- プロジェクトとMySQLなどはすでに紐付けの設定がされている
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Users extends Model
{
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Users;
use Illuminate\Support\Facades\DB;
class HomeController extends Controller
{
public function index(Request $request)
{
/* テーブルから全てのレコードを取得する */
$users = Users::query();
/* ページネーション */
/* レコード数が多い時にページを分割して表示します(今回は5レコードごとにページを分けます) */
/* 分割の必要がなければ省略しても問題ありません */
$posts = $users->paginate(5);
return view('crud.index', ['posts' => $posts]);
/* ページネーションが必要なければ、postsはusersに置き換えます */
}
}
@extends('layouts.app')
@section('content')
<div class="wrapper mx-auto" style="padding-top:30px;">
<!--テーブル-->
<div class="table-responsive">
<table class="table" style="width: 1000px; max-width: 0 auto;">
<tr class="table-info">
<th scope="col" >id</th>
<th scope="col" >名前</th>
<th scope="col" >削除</th>
</tr>
<!--繰り返し処理-->
<!--1レコードずつ情報を表示します-->
@foreach($posts as $user)
<tr>
<td>{{$user->id}}</td>
<td>{{$user->name}}</td>
<!-- blade.php内で変数を利用するためには前後を {{ }} で囲む必要があります -->
<!--削除に必要なボタン要素-->
<td>
<form class="id">
<input data-user_id="{{$companie->id}}" type="submit" class="btn btn-danger btn-dell" value="削除">
</form>
</td>
</tr>
@endforeach
</table>
</div>
<!--ページネーションを表示する変数-->
{{ $posts->links() }}
</div>
コントローラへ非同期通信するためのAjax
<script type="text/javascript">
// トークンを送信する記述
// Laravelでは通信をする際にトークンを送らなければ仕様でエラーが発生する
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
}
});
// ここから非同期処理の記述
$(function() {
//削除ボタンに"btn-danger"クラスを設定しているため、ボタンが押された場合に開始されます
$('.btn-danger').on('click', function() {
var deleteConfirm = confirm('削除してよろしいでしょうか?');
// メッセージをOKした時(true)の場合、次に進みます
if(deleteConfirm == true) {
var clickEle = $(this)
//$(this)は自身(今回は押されたボタンのinputタグ)を参照します
// "clickEle"に対して、inputタグの設定が全て代入されます
var userID = clickEle.attr('data-user_id');
//attr()」は、HTML要素の属性を取得したり設定することができるメソッドです
//今回はinputタグの"data-user_id"という属性の値を取得します
//"data-user_id"にはレコードの"id"が設定されているので
// 削除するレコードを指定するためのidの値をここで取得します
// .ajaxメソッドでルーティングを通じて、コントローラへ非同期通信を行います。
//見本ではレコードを削除するコントローラへ通信を送るためにはweb.phpを参照すると
//通信方法は"post"に設定し、URL(送信先)を'/destroy/{id}'にする必要があります
$.ajax({
type: 'POST',
url: '/destroy/'+userID, //userID にはレコードのIDが代入されています
dataType: 'json',
data: {'id':userID},
})
//”削除しても良いですか”のメッセージで”いいえ”を選択すると次に進み処理がキャンセルされます
} else {
(function(e) {
e.preventDefault()
});
};
});
});
//.ajaxメソッドではオプション(引数)を設定することで送信先(URL)や送信する変数を指定できます
//type は 通信方式をGETもしくはPOSTから選択できます(デフォルトはGETです)
//urlは送信先(URL)を指定します。ルーティングで設定しているURLになるよう文字列と変数を記述します
//dataType はjavascriptからこれから送るデータの種類は何であるかを示します
//json とは "JavaScript Object Notationの略"
//json は javascriptのほかphpや多数の言語でも読み取れるフォーマットなので設定しておけばエラーが出ません
//data はURL先(コントローラー)に渡す値です。今回は削除したいレコードの”id”を渡します。
//dataの書き方は
//data:{'コントローラーのアクションで使う引数':jQueryから渡す変数}になります
</script>
コントローラーへ移動するルーティング
ajaxで指定するURLはルーティングを参照します。
レコードを削除するコントローラーのアクションにつながるURLは
post
の/destroy/{id}
となっているため、ajaxメソッドでの送信先は
/destroy/
+ (idの値が代入されている)変数となります
Auth::routes();
Route::get('/', 'HomeController@index')->name('crud.index'); /* 一覧表示 */
Route::post('/destroy/{id}', 'HomeController@destroy'); /* レコード削除 */
データを受取りレコードを削除するコントローラー
public function destroy(Request $request, Users $users) {
//ajaxメソッドから送信されたデータは$requestに格納されます
//ajas側で送信したデータの名前は"id"という名前に設定しているため
//コントローラーで使うには $request->id で出力します
$users = Users::findOrFail($request->id);
//データベースのUsersテーブルから()で指定されたiDのレコードを代入します
$users->delete();
//usersに代入されているレコード(行)を削除します
}