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
, CONSTRAINTvotes_post_id_foreign
FOREIGN KEY (post_id
) REFERENCESposts
(id
)) (SQL: insert intovotes
(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.