Laravel中的AJAX POST请求[重复]

Posted

技术标签:

【中文标题】Laravel中的AJAX POST请求[重复]【英文标题】:AJAX POST request in Laravel [duplicate] 【发布时间】: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".

调试正在发生的事情的最佳方法是什么?

更新

添加:&lt;meta name="csrf-token" content=" csrf_token() "&gt; 会干扰我在表单中正常使用 `@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。 【参考方案1】:

看看this。你不能在你的 JS 中使用 csrf_token()

在你的 html 中试试这个:

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

这在你的 JS 中:

headers: 
   'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')

【讨论】:

我在文档中看到了这一点,但我看到的每个视频教程都在数据数组中发送了令牌。这是为什么呢? 您也可以将数据数组传递给它(不确定),但您需要拥有元数据并使用 .attr 进入您的 js,因为 csrf_token() 是 Laravel 的东西,您不能调用它在你的 JS 上,实际上你正在发送一个包含 csrf_token() 的字符串 啊,所以如果我要转储数据变量,它真的会是一个字符串吗?我想我只需要离开并提高我的 javascript 知识 是的,它是一个字符串。只是你不能在你的 JS 中调用像 csrf_token() 这样的 PHP,所以它不会被执行。这就是为什么你需要通过一个html标签meta @JesseOrange 很容易理解:它是一个 PHP 函数(它必须是),它生成一个绑定到您的会话的令牌。这些示例显示了在 PHP 中构建 javascript 的版本(作为字符串)。这是非常难看的代码,因为根本不需要在 PHP 中生成 JS。【参考方案2】:

如果您在单个文件中有多个 ajax 调用,那么您可以通过此操作。以下代码适用于您的所有 AJAX 请求。

在你的 html 中试试这个:

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

这在你的 JS 中:

$(document).ready(function() 
        $.ajaxSetup(
            headers: 
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            
        );
);

【讨论】:

以上是关于Laravel中的AJAX POST请求[重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用 Laravel 将 jQuery Ajax POST 请求作为 GET 发送

尽管 Laravel 中的令牌正确,Ajax 调用仍返回 419 错误

Laravel 5.1 AJAX - 即使我发送 POST 请求,也不允许返回 405 GET 方法

Laravel 的 Ajax Post 请求中缺少参数

Ajax Post请求失败[重复]

ajax 请求控制器更新 laravel 中的视图