Laravel 删除可能有错误关系的多态关系

Laravel deleting polymorph relations having possibly wrong relations

我有一个代表用户报告的模型。报表模型具有多态关系,可以包含配方或注释。

目标是能够删除评论或用户,并让 eloquent 删除相关报告。

使用我当前的设置(见下文)这不起作用,删除评论时报告仍然存在并导致错误,因为它现在指向不存在的评论。

我做错了什么?我的多态模型需要 "belongsTo" 关系吗?如果是这样,当关系可变形时我如何建立这种关系?


型号

多态模型

class Report extends Model {
    public function reportable() {
        return $this->morphTo();
    }

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

配方模型

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

    public function reports() {
        return $this->morphMany('App\Report', 'reportable');
    }
}

评论模型

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

    public function reports() {
        return $this->morphMany('App\Report', 'reportable');
    }
}

Laravel 没有内置自动删除相关记录的功能。您需要自己构建此功能,这可以使用模型事件来完成。通常,我会设置一个 deleting 事件来负责删除交易中的相关记录。

A Laravel 5 model observer 看起来像这样:

class RecipeCommentObserver {
    public function deleting($model) {
        try {
            DB::transaction(function() use ($model) {
                /**
                 * Try to delete the necessary related objects when this object is deleted.
                 */

                // detach the many-manys from this model, which will delete
                // the records in the pivot table.
                // e.g. if you had a many-many relationship named 'tags':
                // $model->tags()->detach();

                // the one-one and one-many relations to try and delete
                // for your example, you probably only want 'reports' here.
                // you probably don't to delete the user when deleting a comment.
                $relations = ['reports'];

                foreach ($relations as $relation) {
                    // get a list of all the related ids for this relation
                    $ids = $model->$relation()->lists('id');

                    // use the ->destroy method so any events get fired for the deleted objects
                    // if the amount deleted is less than expected, an error occurred
                    if (!empty($ids) && $model->$relation()->getRelated()->destroy($ids) < count($ids)) {
                        throw new Exception('Error occurred deleting ' . $relation);
                    }
                }
            });
        } catch (Exception $e) {
            throw $e;
        }
    }
}

使用此 class 设置,您可以在 app/Providers/EventServiceProvider.php 中的 boot() 方法中注册观察者:

public function boot(DispatcherContract $events) {
    parent::boot($events);

    RecipeComment::observe(new RecipeCommentObserver());
}