简体   繁体   中英

Laravel 5.6 Eloquent integrity constraint violation when saving quiz record

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:

  • quiz_name
  • quiz_description
  • quiz_pin
  • active

The user_quizzes table contains two foreign keys to reference which quiz belongs to a particular user.

  • user_id
  • quiz_id

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.

Reviewing your code

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.

Solution

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 .

Alternative

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.


Side note

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.

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