Sullivan Berger
Sullivan Berger

Reputation: 33

Laravel - Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails

I am currently learning Laravel through a personal project.

Context

In a blog like application, I need to link an article to its author. When I save the article, I get the error below.

Error

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (parabolica-dev.articles, CONSTRAINT articles_user_id_foreign FOREIGN KEY (user_id) REFERENCES users (id)) (SQL: insert into articles (title, content, excerpt, updated_at, created_at) values (rgergregerg, regergergregerg, regregregregreg, 2020-04-29 09:55:12, 2020-04-29 09:55:12))

Models

Article

class Article extends Model
{
    protected $fillable = ['title', 'content', 'excerpt', 'user_id'];

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

User

class User extends Authenticatable
{
    protected $fillable = [
        'name', 'email', 'password',
    ];

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

Migrations

Users

class CreateUsersTable extends Migration
{
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('users');
    }
}

Articles

class CreateArticlesTable extends Migration
{
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->string('title');
            $table->text('excerpt');
            $table->text('content');
            $table->string('type');
            $table->string('status');

            // Relationship between article and user

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

    public function down()
    {
        Schema::dropIfExists('articles');
    }
}

Controller

ArticleController

class ArticleController extends Controller
{
    public function store(StoreArticle $request)
    {
        $validatedData = $request->validated();

        $user = Auth::user()->id;
        $article = Article::create($validatedData);
        $article->user_id = $user;
        $request->session()->flash('status', 'Article was created!');

        return redirect()->route('articles.show', ['article' => $article->id]);
    }
}

Solutions tried

Those are the 2 most proposed solutions across SO / LaravelCasts from what I found. Any suggestions on what I did wrong ?

Thanks for helping me !

Upvotes: 1

Views: 11703

Answers (3)

kepson diazz
kepson diazz

Reputation: 11

You must add a nullable function to your foreign column::

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

Upvotes: 0

A.A Noman
A.A Noman

Reputation: 5270

You have to change this three lines. You insert a row but at the time user_id is null. That's why it shows the error because you assigned the user_id field not nullable.

$article = new Article;
$article->fill($validatedData); 
$article->user_id = Auth::user()->id;
$article->save();

Upvotes: 1

Fitzi
Fitzi

Reputation: 1673

The create method creates and saves a new instance of your model. Since the model does not include the users id at that point, it fails.

You could fix that by adding user_id to the fillables array of your model and also add the user id to the $validatedData array before creating the model.

Alternatively, you can also create a new instance of your model with the new keyword, set all data and explicitely save it once you're done:

$article = new Article($validatedData);
$article->user()->associate( Auth::user() );
$article->save();

Upvotes: 4

Related Questions