当我使用以下语法删除一行时:

$user->delete();

是否有一种方法来附加一个类型的回调,这样它就会自动这样做:

$this->photo()->delete();

最好是在模型类内部。


当前回答

有3种方法可以解决这个问题:

1. 在模型引导上使用雄辩事件(参考:https://laravel.com/docs/5.7/eloquent#events)

class User extends Eloquent
{
    public static function boot() {
        parent::boot();

        static::deleting(function($user) {
             $user->photos()->delete();
        });
    }
}

2. 使用雄辩的事件观察者(参考:https://laravel.com/docs/5.7/eloquent#observers)

在你的AppServiceProvider中,像这样注册观察者:

public function boot()
{
    User::observe(UserObserver::class);
}

接下来,添加一个Observer类,如下所示:

class UserObserver
{
    public function deleting(User $user)
    {
         $user->photos()->delete();
    }
}

3.使用外键约束(参考:https://laravel.com/docs/5.7/migrations#foreign-key-constraints)

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

其他回答

在我的情况下,这是相当简单的,因为我的数据库表是InnoDB与外键级联删除。

因此,在这种情况下,如果照片表包含用户的外键引用,那么您所要做的就是删除酒店,清理工作将由数据库完成,数据库将从数据库中删除所有照片记录。

或者你也可以这样做,只是另一个选择:

try {
    DB::connection()->pdo->beginTransaction();

    $photos = Photo::where('user_id', '=', $user_id)->delete(); // Delete all photos for user
    $user = Geofence::where('id', '=', $user_id)->delete(); // Delete users

    DB::connection()->pdo->commit();

}catch(\Laravel\Database\Exception $e) {
    DB::connection()->pdo->rollBack();
    Log::exception($e);
}

注意,如果你没有使用默认的laravel db连接,那么你需要执行以下操作:

DB::connection('connection_name')->pdo->beginTransaction();
DB::connection('connection_name')->pdo->commit();
DB::connection('connection_name')->pdo->rollBack();

使用限制()

Laravel 7之后,有了新的foreignId()和constrained()方法来定义数据库中的关系约束。可以在这些方法上使用OnDelete()方法自动删除相关记录。

古老的风格

$table->unsignedBigInterer('user_id');

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

新风格

$table->foreignId('user_id')
      ->constrained()
      ->onDelete('cascade');

注意:这个答案是为Laravel 3编写的。因此,在Laravel的最新版本中可能会或可能不会很好地工作。

在真正删除用户之前,您可以删除所有相关照片。

<?php

class User extends Eloquent
{

    public function photos()
    {
        return $this->has_many('Photo');
    }

    public function delete()
    {
        // delete all related photos 
        $this->photos()->delete();
        // as suggested by Dirk in comment,
        // it's an uglier alternative, but faster
        // Photo::where("user_id", $this->id)->delete()

        // delete the user
        return parent::delete();
    }
}

希望能有所帮助。

最好为此重写delete方法。这样,您就可以在delete方法本身中合并DB事务。如果你使用事件方式,你将不得不覆盖你的删除方法调用与DB事务每次你调用它。

在你的用户模型中。

public function delete()
{
    \DB::beginTransaction();

     $this
        ->photo()
        ->delete()
    ;

    $result = parent::delete();

    \DB::commit();

    return $result;
}