weixin_33737134 2018-06-01 09:17 采纳率: 0%
浏览 108

Laravel中的AJAX POST请求[重复]

This question already has answers here:
                </div>
            </div>
                    <div class="grid--cell mb0 mt4">
                        <a href="/questions/28417781/jquery-add-csrf-token-to-all-post-requests-data" dir="ltr">jQuery add CSRF token to all $.post() requests' data</a>
                            <span class="question-originals-answer-count">
                                (6 answers)
                            </span>
                    </div>
            <div class="grid--cell mb0 mt8">Closed <span title="2019-01-11 16:41:50Z" class="relativetime">last year</span>.</div>
        </div>
    </aside>

I have an AJAX request which is a GET request.

/**
 * 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');
            }
        }
    });
});

Where the URL is: http://127.0.0.1:8000/like/article/145

And is grabbed via the href attribute of .like, the markup of which looks like this:

<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>

The LikeController looks like this:

<?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();
            }
        }
    }
}

I think it's extremely bad practice to update a database via a GET request

So, I changed the Route to use POST and updated the AJAX call to:

/**
 * 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');
            }
        }
    });
});

As you can see, I've changed the method and added in the CSRF token, however, I get an error:

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".

What is the best way to debug what's going on?

Update

By adding: <meta name="csrf-token" content="{{ csrf_token() }}"> would it interfer with my normal use of `@csrf' in my forms?

Also, I added a fail callback to the request

}).fail(function (jqXHR, textStatus, error) {
    // Handle error here
    console.log(jqXHR.responseText);
});

Another update

As you have all kindly pointed out, in the documentation here, it does indeed say, set the meta CSRF attribute, I even had an error in my console saying this wasn't defined, but I misinterpreted the error.

Why though, in some tutorials, do people add the CSRF token to the data array?

</div>
  • 写回答

2条回答 默认 最新

  • ??yy 2018-06-01 09:25
    关注

    Look at this. You can't use {{ csrf_token() }} in your JS.

    Try this in your html :

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

    And this in your JS :

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

报告相同问题?

悬赏问题

  • ¥35 平滑拟合曲线该如何生成
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集