【问题标题】:Delete related models in Laravel 6/7在 Laravel 6/7 中删除相关模型
【发布时间】:2020-09-03 18:13:33
【问题描述】:

有很多相关的问题,但很遗憾我找不到有效的解决方案

我有 Laravel 模型,当这个模型被删除时我想要

  1. 删除部分相关模型
  2. 删除模型时运行自定义 SQL 查询

我的 Laravel 的模型类看起来像(你可以看到模型可以有不同的关系类型)

class ModelA extends Model
{
  public functions modelsB() {
    return $this->hasMany(ModelB:class);
  }

  public functions modelsC() {
    return $this->belongsToMany(ModelC:class);
  }

  // other related models
 
  // place where I am expecting actual deleting is happening
  public static function boot() {
        parent::boot();

        self::deleting(function($modelA) { 

          $modelA->modelsB()->get()->each->delete(); 
         
          foreach($modelA->modelsC as $modelC){
            $modelC->delete();
          }
    });
  }
}

ModelA 已删除,但所有相关数据仍保留,我不确定它是否被调用。也许我错过了什么?我应该为我的 ModelA 扩展一些课程吗?还是这个引导函数应该放在别的地方?

【问题讨论】:

  • 为什么不直接覆盖删除方法?
  • 设置外键在删除时级联是一种选择,如果您还没有尝试过的话。
  • 我想在声明模型关系的地方继续删除逻辑
  • 你试过$modelA->modelsB()->delete()$modelA->modelsC()->delete()吗?
  • 您检查过deleting 实际触发的事件吗?通过调试器或logger()->debug() 或其他方式。

标签: laravel eloquent cascading-deletes


【解决方案1】:

https://laravel.com/docs/7.x/eloquent#events-using-closures 呢?类似的东西

class ModelA extends Model
{
    public functions modelsB()
    {
        return $this->hasMany(ModelB::class);
    }

    /**
     * The "booted" method of the model.
     *
     * @return void
     */
    protected static function booted()
    {
        static::deleted(function ($modelA) {
            $modelA->modelsB()->delete();
            // ...
        });
    }
}

【讨论】:

    【解决方案2】:

    您是否像这样在 ModelB 的迁移文件中级联它:

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

    `onDelete('cascade') 是重要部分,请注意这是以下的简写:

    $table->unsignedBigInteger('modelA_id');
    
    $table->foreign('modelA_id')->references('id')
        ->on('modelA')->onDelete('cascade');
    

    这应该为您完成大部分繁重的工作,您可以在Laravel Docs Migrations找到更多信息

    如果您不喜欢这种方法并且更喜欢基于事件的方法,请尝试在您的 ModelA 类中执行此操作:

    protected static function booted()
    {
        static::deleted(function ($modelA) {
            $modelA->modelsB()->delete();
            // ...
        });
    }
    

    【讨论】:

      【解决方案3】:

      您是否尝试过使用static 而不是self

      documentation 中,Laravel 建议在绑定事件或观察者时使用static 关键字

      【讨论】:

        【解决方案4】:

        如果您尝试从模型本身中删除相关模型。你只需要调用$this->reletedModel()->delete(); 真的不需要foreach()循环。

        假设您有一个定义与以下声明的关系的函数。

        public function relatedModel()
        {
            return $this->hasOne(RelatedModel::class);
            //OR
            //return $this->hasMany(RelatedModel::class);
        }
        
        /** Function to delete related models */
        public function deleteRelatedModels()
        {
            return $this->relatedModel()->delete();
        }
        

        【讨论】:

          【解决方案5】:

          我建议使用Observers 来监听ModelA 删除事件。

          1. 运行php artisan make:observer ModelAObserver --model=ModelA
          2. AppServiceProviderboot() 方法中添加ModelA::observe(ModelAObserver::class);
          3. 现在在 ModelAObserver 中的 deleted() 方法中,您将删除关联的模型并执行自定义 SQL 查询。
          /**
           * Handle the ModelA "deleted" event.
           *
           * @param  \App\ModelA  $modelA
           * @return void
           */
          public function deleted(ModelA $modelA)
          {
              // delete associated models
              
              $modelA->modelsB()->delete();
              $modelA->modelsC()->delete()
          
              ... 
          
              // perform custom SQL queries
          
              ... 
          }
          

          您还需要在 ModelA 上调用 delete 的任何位置添加数据库事务,以确保该操作已完全完成。

          DB::transaction(function () use ($modelA) {
             $modelA->delete();
          });
          

          【讨论】:

            猜你喜欢
            • 2015-02-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-12-10
            • 2014-06-09
            • 1970-01-01
            • 2018-06-27
            • 2018-04-15
            相关资源
            最近更新 更多