Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

alpha's avatar

Laravel Relationship - Foreign key delete

Hey everyone, I am confuse about the laravel relationship..

Currently I am trying the laravel 'Intermediate Task List', I edited the task table to

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

i re run the migration and created 1 user with 2 task I was expecting that the task would get deleted once i delete the user.. but it wont? what mistake did i do?

0 likes
10 replies
lindstrom's avatar
Level 15

Edit for lack of coffee when originally responding and for much greater clarity.

  1. You should be able to do exactly as you ask (assuming here that the user's id is 1)
$user = App\User::find(1);
$user->delete();

If the foreign key's onDelete clause is defined, (which in your case it is), the user and ALL rows in other tables defined as you note in your example.

Your create_tasks_table foreign key should look like something like this:

$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

Yours looks fine. Let's move on to testing some things. Use php artisan tinker and try this (assuming your user id is 1):

$user = App\User::find(1)->delete();

Tinker should output => true

Check your database. Is the user deleted? Are the user's tasks deleted?

  1. Try to run the query directly against the db and see what happens:
DELETE FROM users WHERE id = 1;

Was the user and the user's tasks deleted?

3a. From within Laravel, you can use the DB facade to wrap the delete function:

DB::delete('DELETE FROM users WHERE id = 1');
  1. You don't need to necessarily create foreign keys with the delete behavior. You can achieve deletion in the manner you are seeking by Relationship in your User model
public function tasks()
{
    return $this->hasMany('App\Task');
}

And then,

$user = User::find($id);
$user->tasks()->delete();
$user->delete();

If you have foreign keys with cascading deletion, the point I was making is that the database will enforce those constraints. Some people would rather have more precise control over exactly what gets deleted. If you define foreign keys and casade deletion anywhere you reference, for example, a user's id, you have to remember that when a user is deleted all rows for that user in foreign tables will be deleted. Using Eloquent, you can be explicit about what gets deleted. I digress, that goes well beyond the scope of your question.

The tl;dr is that what you did should work? Without errors or code or other details all you can do is try a few other methods and see if you get the desired results.

5 likes
michaelrtm's avatar

So why doesn't

$user = User::find($id);
$user->delete();

also remove tasks? Is it not doing the same as what using the DB facade would achieve?

I thought the point of defining the cascade was to prevent having to manually delete everything related?

thomaskim's avatar

The database should delete the tasks if the user is deleted. It doesn't work the other way around.

alpha's avatar

Well @lindstrom I tried it but it still wont work

$user = App\User::find(1)->delete();

I ran this but the task is still there, access sqlite3

select * from users; // empty
select * from tasks; // 1 record

Then i ran php artisan migrate:refresh

create 1 user 1 record -> access sqlite3

DELETE FROM users WHERE id = 1;

still got 1 record.. I still don't get it.. why wont it get deleted?.. does this mean that this method wont work for the users table only...? Will try other table..

thomaskim's avatar

@alpha If you're using sqlite, I'm reading that it is disabled by default.

Try adding this to the boot method of your app/Providers/AppServiceProvider:

if (DB::connection() instanceof Illuminate\Database\SQLiteConnection) {
  DB::statement(DB::raw('PRAGMA foreign_keys=1'));
}
andreich1980's avatar

I have the same problem. L5.3

PRAGMA foreign_keys; returns 1

my migration for product_photos table

$table->integer('product_id')->unsigned();
            $table->foreign('product_id')
                ->references('id')->on('products')
                ->onDelete('cascade');

I added the code to the boot method of AppServiceProvider

if (\DB::connection() instanceof Illuminate\Database\SQLiteConnection) {
    \DB::statement(DB::raw('PRAGMA foreign_keys=1'));
}

And I also tried to run PRAGMA foreign_keys = ON in the DB console.

Still nothing, when I delete a row from the product table - related row in product_photos stays.

Borisu's avatar

Hi,

  1. If you try to cascade, then you should do so on all tables referencing the item_id, so long the corresponding migrations reference it as a foreign key constraint.
  2. When using sqlite the cascading should be enabled (it's not by default for compatibility reasons)

Hope this helps ;)

sutara79's avatar

@andreich1980 Laravel 5.4. It works.

// if (\DB::connection() instanceof Illuminate\Database\SQLiteConnection) {
if (\DB::getDriverName() == 'sqlite') {
    \DB::statement(\DB::raw('PRAGMA foreign_keys=1'));
}
1 like

Please or to participate in this conversation.