使用Laravel的Eloquent删除hasManyThrough关系行

时间:2016-11-16 16:24:51

标签: php laravel eloquent has-many-through

我有三个模型,[x; y]AdvertiserPtcAd。删除广告商时,我想删除所有相关的 PtcAds PtcCampaigns 广告商通过 PtcAds 有许多 PtcCampaigns

广告客户模式

PtcCampaign

PtcAd模型

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();
}

PtcCampaign模型

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();
}

我的测试:

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)); } 测试中的$this->assertFalse(PtcCampaign::all()->contains($ptcCampaign))失败了,为什么?

我有更多测试来确保所有关系都有效,所以我真的不知道可能出现什么问题。我的下一次尝试是在广告客户的delete()方法中制作test_delete_advertiser(),但也许有一些更简单的东西,我想了解为什么这不起作用。

2 个答案:

答案 0 :(得分:2)

看起来问题在于删除语句的顺序。

尝试更改以下序列:

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

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

    return parent::delete();
}

答案 1 :(得分:1)

您可以使用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...
        });
    }
}

希望这有帮助!