I'm currently working on a quiz application with Laravel 5.6 and am having trouble with saving a new quiz record.
The two tables that are being inserted into are quizzes
and user_quizzes
. The quizzes
table contains some basic quiz data such as:
The user_quizzes
table contains two foreign keys to reference which quiz belongs to a particular user.
The error is an integrity constraint violation when inserting into the user_quizzes
table. It successfully inserts the quiz_id
but the user_id
is left as NULL. I am unsure how to ensure the user_id
is also inserted as I'm using Eloquent.
The full error is:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'user_id' cannot be null (SQL: insert into `user_quizzes` (`quiz_id`, `user_id`) values (6, ))
I am making use of the QuizController
, Quiz Model
and User Model
for saving the record. Here is my store()
method in the QuizController
:
public function store(Request $request)
{
$validator = $request->validate([
'quiz_name' => 'required|max:30',
'quiz_description' => 'required|max:500'
]);
$quiz = new Quiz(
[
'quiz_name' => $request->get('quiz_name'),
'quiz_description' => $request->get('quiz_description'),
'active' => '0',
'quiz_pin' => '5555', // hard coded for now
]
);
$quiz->save();
$user = new User;
$user->quizzes()->save($quiz);
return redirect()->route('quiz_host.dashboard.manage-quizzes')->with('quizCreated', 'Whoa ' . Auth::user()->username . ', you have created a quiz! Now it\'s time to add some questions');
}
My User
Model is a follows:
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'username', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function activation()
{
return $this->hasOne('App\Models\Activation');
}
public function profile()
{
return $this->hasOne('App\Models\Profile');
}
public function quizzes()
{
return $this->belongsToMany(Quiz::class, 'user_quizzes', 'user_id', 'quiz_id');
}
}
and my Quiz
model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Quiz extends Model
{
protected $table = 'quizzes';
protected $fillable = ['quiz_name', 'quiz_description', 'active', 'quiz_pin'];
public function user()
{
return $this->belongsToMany(User::class, 'user_quizzes', 'quiz_id', 'user_id');
}
}
Any guidance as to what I'm doing wrong would be greatly appreciated.
This is your controller:
QuizController.php
public function store(Request $request)
{
// your validations.
// Storing the quiz.
$quiz->save();
// User instance.
$user = new User;
// Storing the relationship.
$user->quizzes()->save($quiz);
// Returning the view.
return redirect()->route('quiz_host.dashboard.manage-quizzes')->with('quizCreated', 'Whoa ' . Auth::user()->username . ', you have created a quiz! Now it\'s time to add some questions');
}
Now, the problem here is related to the $user
object.
When you do this:
$user = new User;
You are createing an instance of the User
class, but this object isn't persisted yet into the database, what this means is that this object doens't have an id
yet. You can confirm this doing dd($user->id)
, this will return null
.
That's why when you do this:
$user->quizzes()->save($quiz);
It throws the SQL error, because you are calling a method to store the $primaryKey
( id
) of the $user
object in the pivot table. But given that the $user
object doens't have a primary key is trying to store a null
value instead.
Now, I don't really know what is your "use case", but I will assume that the $user
is the logged-in one, so to relate properly the relationship replace this:
// creating a User instance.
$user = new User;
with this:
// Logged-in user.
$user = auth()->user();
This will use the auth facade to get the actual logged-in user and return the object. Given that is a registered user it will have a proper id
.
If your use case is different and you will relate the quiz to a different user, do this instead:
// Some other user
$user = User::find($someId); // $user = User::find(5); for example
or this, to create a completely new User
instance and relating a quiz to it:
// A new User
$user = new User;
$user->fill($someData);
$user-save(); // this will assign a primary key (id) to the object.
Now you can attach the related model to it.
Your users m--------m quizzes
is a many to many relationship .
So, as the documentation says , the proper way to store a relatioship between the two objects is the attach()
method:
$user->quizzes()->attach($quiz->id);
This method will create a record in the intermediate table (pivot) with the ids of the $user
and $quiz
objects.
To make it clear, new User
will only create user model object, it is still not committed to DB.
When we try to call $user->quizzes()->save($quiz)
it is will try to add an entry in user_quizzes pivot table, but user_id is empty, because user is still not created.
So you have to create a user entry in DB by calling $user->save()
before adding it to pivot table.
$quiz->save();
$user = new User;
$user->save();
$user->quizzes()->save($quiz);
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.