【问题标题】:Delete hasManyThrough relationship rows using Laravel's Eloquent使用 Laravel 的 Eloquent 删除 hasManyThrough 关系行
【发布时间】:2017-03-30 22:49:13
【问题描述】:

我有三个模型,AdvertiserPtcAdPtcCampaign。删除 广告商 时,我想删除所有相关的 PtcAdsPtcCampaigns广告商有许多PtcCampaignsPtcAds

广告商模型

use SoftDeletes;

protected $dates = ['deleted_at'];

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

public function ptcCampaigns()
{
    return $this->hasManyThrough('App\PtcCampaign', 'App\PtcAd');
}

public function delete()
{
    $this->ptcAds()->delete();
    // I'VE TRIED WITH AND WITHOUT THIS
    $this->ptcCampaigns()->delete();

    return parent::delete();
}

PtcAd 模型

use SoftDeletes;

protected $fillable = ['advertiser_id', 'title'];

protected $dates = ['deleted_at'];

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

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

public function delete()
{
    $this->ptcCampaigns()->delete();

    return parent::delete();
}

PtcCampaign 模型

use SoftDeletes;

public $timestamps = false;

protected $fillable = ['ptc_ad_id', 'clicks'];

protected $dates = ['paused_at', 'deleted_at'];

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

我的测试:

public function test_delete_advertiser()
{
    $advertiser = factory(Advertiser::class)->create();

    $ptcAd = factory(PtcAd::class)->create(['advertiser_id' => $advertiser->id]);

    $ptcCampaign = factory(PtcCampaign::class)->create(['ptc_ad_id' => $ptcAd->id]);

    $this->assertTrue($advertiser->delete());
    $this->assertFalse(Advertiser::all()->contains($advertiser));
    $this->assertFalse(PtcAd::all()->contains($ptcAd));

    // THE FOLLOWING TEST DOESN'T WORK!
    $this->assertFalse(PtcCampaign::all()->contains($ptcCampaign));
}

// ALL OF THE FOLLOWING TESTS WORK!
public function test_delete_ad()
{
    $ptcAd = factory(PtcAd::class)->create();

    $ptcCampaign = factory(PtcCampaign::class)->create(['ptc_ad_id' => $ptcAd->id]);

    $this->assertTrue($ptcAd->delete());
    $this->assertFalse(PtcAd::all()->contains($ptcAd));
    $this->assertFalse(PtcCampaign::all()->contains($ptcCampaign));
}

test_delete_advertiser() 测试中的$this->assertFalse(PtcCampaign::all()->contains($ptcCampaign)) 失败,为什么?

我有更多的测试来确保所有的关系都能正常工作,所以我真的不知道可能出了什么问题。我的下一个尝试是在 Advertiser 的 delete() 方法中创建 foreach,但也许有更简单的方法,我想了解为什么这不起作用。

【问题讨论】:

    标签: php laravel eloquent has-many-through


    【解决方案1】:

    看来问题出在delete语句的顺序上。

    尝试改变如下顺序:

    public function delete()
    {
        $this->ptcCampaigns()->delete();
    
        $this->ptcAds()->delete();
    
        return parent::delete();
    }
    

    【讨论】:

    • 就是这样!谢谢!现在我有另一个相关的问题,由于PtcAd模型设置了delete()方法来删除关系中的PtcCampaigns,为什么我需要从Advertiser模型中调用$this->ptcCampaigns()->delete();?不应该连锁吗?
    • 当您执行$this->ptcAds()->delete() 时,它会创建查询并删除行,因此它会调用delete 函数查询构建器类。但是如果你使用foreach删除ptcAds,那么它会调用Model类的delete函数,同时也会删除ptcCampaigns
    【解决方案2】:

    您可以使用 Laravel 的模型事件 (deleting) 删除相关模型,如下所示:

    class Advertiser extends Eloquent
    {
        public function ptcAds()
        {
            return $this->hasMany('PtcAd');
        }
    
        // this is a recommended way to declare event handlers
        protected static function boot() {
            parent::boot();
    
            static::deleting(function($adv) { // before delete() method call this
                 $adv->ptcAds()->delete();
                 // do the rest of the cleanup...
            });
        }
    }
    
    // Same for PtcCompaigns
    
    class PtcAd extends Eloquent
    {
        public function ptcCompaigns()
        {
            return $this->hasMany('PtcCompaigns');
        }
    
        // this is a recommended way to declare event handlers
        protected static function boot() {
            parent::boot();
    
            static::deleting(function($ptc_ad) { // before delete() method call this
                 $ptc_ad->ptcCompaigns()->delete();
                 // do the rest of the cleanup...
            });
        }
    }
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2020-10-14
      • 2016-09-26
      • 2019-03-26
      • 2015-07-27
      • 1970-01-01
      • 2015-05-14
      • 1970-01-01
      • 2020-02-02
      • 1970-01-01
      相关资源
      最近更新 更多