【发布时间】:2018-11-11 09:30:17
【问题描述】:
我有一个 AJAX 请求,它是一个 GET 请求。
/**
* AJAX Like function
*/
$(".like").click(function (e) {
e.preventDefault(); // you dont want your anchor to redirect so prevent it
$.ajax({
type: "GET",
// blade.php already loaded with contents we need, so we just need to
// select the anchor attribute href with js.
url: $('.like').attr('href'),
success: function () {
if ($('.like').hasClass('liked')) {
$(".like").removeClass("liked");
$(".like").addClass("unliked");
$('.like').attr('title', 'Like this');
} else {
$(".like").removeClass("unliked");
$(".like").addClass("liked");
$('.like').attr('title', 'Unlike this');
}
}
});
});
网址在哪里:http://127.0.0.1:8000/like/article/145
并通过.like的href属性抓取,其标记如下:
<div class="interaction-item">
@if($article->isLiked)
<a href="{{ action('LikeController@likeArticle', $article->id) }}" class="interactor like liked" role="button" tabindex="0" title="Unlike this">
@else
<a href="{{ action('LikeController@likeArticle', $article->id) }}" class="interactor like unliked" role="button" tabindex="0" title="Like this">
@endif
<div class="icon-block">
<i class="fas fa-heart"></i>
</div>
</a>
</div>
LikeController 看起来像这样:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use App\Like;
use App\Article;
use App\Event;
use Illuminate\Support\Facades\Auth;
class LikeController extends Controller
{
/**
* Display all liked content for this user
*/
public function index()
{
$user = Auth::user();
$articles = $user->likedArticles()->get();
$articleCount = count($articles);
$events = $user->likedEvents()->get();
$eventCount = count($events);
return view('pages.likes.index', compact('articles', 'articleCount', 'events', 'eventCount'));
}
/**
* Handle the liking of an Article
*
* @param int $id
* @return void
*/
public function likeArticle($id)
{
// here you can check if product exists or is valid or whatever
$this->handleLike(Article::class, $id);
return redirect()->back();
}
/**
* Handle the liking of an Event
*
* @param int $id
* @return void
*/
public function likeEvent($id)
{
// here you can check if product exists or is valid or whatever
$this->handleLike(Event::class, $id);
return redirect()->back();
}
/**
* Handle a Like
* First we check the existing Likes as well as the currently soft deleted likes.
* If this Like doesn't exist, we create it using the given fields
*
*
* @param [type] $type
* @param [type] $id
* @return void
*/
public function handleLike($type, $id)
{
$existingLike = Like::withTrashed()
->whereLikeableType($type)
->whereLikeableId($id)
->whereUserUsername(Auth::user()->username)
->first();
if (is_null($existingLike)) {
// This user hasn't liked this thing so we add it
Like::create([
'user_username' => Auth::user()->username,
'likeable_id' => $id,
'likeable_type' => $type,
]);
} else {
// As existingLike was not null we need to effectively un-like this thing
if (is_null($existingLike->deleted_at)) {
$existingLike->delete();
} else {
$existingLike->restore();
}
}
}
}
我认为通过 GET 请求更新数据库是非常糟糕的做法
所以,我将路由更改为使用 POST 并将 AJAX 调用更新为:
/**
* AJAX Like function
*/
$(".like").click(function (e) {
e.preventDefault(); // you dont want your anchor to redirect so prevent it
$.ajax({
type: "POST",
// blade.php already loaded with contents we need, so we just need to
// select the anchor attribute href with js.
url: $('.like').attr('href'),
data: {
_token: '{{ csrf_token() }}'
},
success: function () {
if ($('.like').hasClass('liked')) {
$(".like").removeClass("liked");
$(".like").addClass("unliked");
$('.like').attr('title', 'Like this');
} else {
$(".like").removeClass("unliked");
$(".like").addClass("liked");
$('.like').attr('title', 'Unlike this');
}
}
});
});
如您所见,我已更改方法并添加到 CSRF 令牌中,但是,我收到错误:
POST http://127.0.0.1:8000/like/article/145 419 (unknown status)
send @ app.js:14492
ajax @ app.js:14098
(anonymous) @ app.js:27608
dispatch @ app.js:10075
elemData.handle @ app.js:9883
app.js:14492 XHR failed loading: POST "http://127.0.0.1:8000/watch/article/145".
调试正在发生的事情的最佳方法是什么?
更新
添加:<meta name="csrf-token" content="{{ csrf_token() }}"> 会干扰我在表单中正常使用 `@csrf' 吗?
另外,我在请求中添加了一个失败回调
}).fail(function (jqXHR, textStatus, error) {
// Handle error here
console.log(jqXHR.responseText);
});
另一个更新
正如大家所指出的那样,在文档here 中,它确实说设置元 CSRF 属性,我什至在我的控制台中有一个错误,说这没有定义,但我误解了这个错误。
为什么在某些教程中,人们会将 CSRF 令牌添加到数据数组中?
【问题讨论】:
-
函数的路由是否存在?
-
您是否尝试过查看 POST 的响应?通常它会在控制器中显示错误。
-
首先,您已将 _token 添加到数据而不是标头中,其次您实际上并未发送令牌,而是发送了文字字符串,您使用的是什么版本的 laravel 因为我知道 Laravel 默认在 bootstrap.js 文件中设置了全局变量。检查您的
storage/logs/laravel.log -
我会更新我的问题
-
另一件事我注意到你应该使用
url: $(this).attr('href'),因为当你在like按钮的点击函数中时它很可能会破坏并使用$(this),因为它是一个类而不是一个ID。