简体   繁体   中英

Laravel 5: SQLSTATE[23000]: Integrity constraint violation, foreign key constraint fails

I am building an upvote/downvote system in Laravel 5 using AJAX. I am also using this jquery plugin to display the voting button: https://github.com/janosgyerik/jquery-upvote

But I keep getting this error. It also appears that it is ignoring the post_id field completely (due to my relations?) and it is not submitting any value from the buttons in the value field.

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails ( laravel_5 . votes , CONSTRAINT votes_post_id_foreign FOREIGN KEY ( post_id ) REFERENCES posts ( id )) (SQL: insert into votes ( value , user_id , updated_at , created_at ) values (, 2, 2015-09-14 22:02:11, 2015-09-14 22:02:11))

I've tried a couple of things, first I used save() instead of create() like so

Auth::user()->votes()->save($request->all());

But that gave another error

ErrorException in HasOneOrMany.php line 210: Argument 1 passed to Illuminate\\Database\\Eloquent\\Relations\\HasOneOrMany::save() must be an instance of Illuminate\\Database\\Eloquent\\Model, array given, called in C:\\xampp\\htdocs\\laravel-5\\app\\Http\\Controllers\\VotesController.php on line 63 and defined

Even though I was including Illuminate\\Database\\Eloquent\\Model in the controller.

I have also tried using this instead

App\User::find(Auth::user()->id)->votes()->save($request->all());

But I got Class 'App\\Http\\Controllers\\App\\User' not found even though I was including App\\User

There some amount of code involved so please bear with me.

Migration file

public function up()
    {
        Schema::create('votes', function(Blueprint $table) {
            $table->increments('id');
            $table->integer('value');
            $table->integer('user_id')->unsigned();
            $table->integer('post_id')->unsigned();
            $table->timestamps();

            $table->foreign('user_id')
                    ->references('id')
                    ->on('users');

            $table->foreign('post_id')
                ->references('id')
                ->on('posts');
        });
    }

Route

Route::resource('votes', 'VotesController');

VotesController.php

public function store(Requests\VoteRequest $request)
    {
        // AJAX JSON RESPONSE
        $response = array(
            'status' => 'success',
            'msg' => 'Article has been posted. Redirecting now.',
        );

        if(Auth::check()){
            \Log::info(Auth::user());
            Auth::user()->votes()->create($request->all());
        } else {
                return \Response::json('Nope');
        }

        return \Response::json($response);
    }

Vote.php Model

class Vote extends Model
{
    protected $fillable = [
        'value'
    ];

    protected $primaryKey = 'post_id';

    public function user() {
        return $this->belongsTo('App\User');
    }

    public function posts() {
        return $this->belongsTo('App\Post');
    }
}

User.php Model

public function votes() {
        return $this->hasMany('App\Vote');
    }

Post.php Model

public function votes() {
        return $this->hasMany('App\Vote');
    }

Relevant part of the View: show.blade.php

{!! Form::open(['url' => 'votes', 'id' => 'votes']) !!}
    <div class="upvote topic">
      <a class="upvote" data-value="1" id="value"></a>
         <span class="count">0</span>
         <a class="downvote" data-value="-1" id="value"></a>
    </div>
{!! Form::close() !!}

The Javascript

$(document).ready(function() {
            $('.topic').upvote();

            $('#votes').on('click', function (e) {
                e.preventDefault();
                var value = $('#value').val();
                $.ajaxSetup({
                    headers: {
                        'X-CSRF-TOKEN': $('[name="_token"]').val()
                    }
                });
                $.ajax({
                    type: "POST",
                    url: 'http://localhost/laravel-5/public/votes',
                    dataType: 'JSON',
                    data: {value: value},
                    success: function( data ) {

                        //console.log(data);

                        if(data.status == 'success') {
                            alert(data.msg);

                        } else {
                            alert('error');
                            console.log(data.msg);
                        }
                    }
                });
            });
        });

You've got a whole bunch of issues here. Let's focus just on the frontend stuff for a moment. You are using the same HTML ID in multiple places, which is invalid and causing you to read the wrong element, you are using .val() when you should be using .data('value') to retrieve data from an element, and the post_id does not seem to be anywhere in your code, and definitely not included in your ajax request.

Starting with show.blade.php

{!! Form::open(['url' => 'votes', 'class' => 'votes']) !!}
<div class="topic" data-post="{{ $post->id }}">
  <a class="upvote vote" data-value="1"></a>
  <span class="count">0</span>
  <a class="downvote vote" data-value="-1"></a>
</div>
{!! Form::close() !!}

Presuming you have a $post object available in that view. Otherwise you need to get the post_id from somewhere in order to include it here. Now in your Javascript:

$('.topic').upvote();

$('.vote').on('click', function (e) {
  e.preventDefault();
  var data = {value: $(this).data('value'), post_id: $(this).parent().data('post')};
  $.ajaxSetup({
    headers: {
      'X-CSRF-TOKEN': $('[name="_token"]').val()
    }
  });
  $.ajax({
    type: "POST",
    url: 'http://localhost/laravel-5/public/votes',
    dataType: 'JSON',
    data: data
  });
});

This should at least get your POST request sending the correct data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM