[英]Delete hasManyThrough relationship rows using Laravel's Eloquent
I have three models, Advertiser
, PtcAd
, and PtcCampaign
. 我有三个模型,
Advertiser
, PtcAd
和PtcCampaign
。 When deleting a Advertiser I want to delete all related PtcAds and PtcCampaigns . 删除广告商时,我想删除所有相关的PtcAd和PtcCampaigns 。 The Advertiser has many PtcCampaigns through PtcAds .
广告 商通过PtcAds有许多PtcCampaigns 。
Advertiser Model 广告商模型
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 Model 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 Model 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');
}
My tests: 我的测试:
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));
}
The $this->assertFalse(PtcCampaign::all()->contains($ptcCampaign))
in the test_delete_advertiser()
test fails, why? test_delete_advertiser()
测试中的$this->assertFalse(PtcCampaign::all()->contains($ptcCampaign))
失败,为什么?
I have more tests to make sure all the relationships work so I really don't know what could possibly be wrong. 我有更多的测试来确保所有的关系都能正常工作,所以我真的不知道可能出现什么问题。 My next attempt would be to make
foreach
in the Advertiser's delete() method but maybe there's something simpler and I want to understand why this doesn't work. 我的下一个尝试是在广告商的delete()方法中制作
foreach
,但也许有一些更简单的东西,我想知道为什么这不起作用。
It looks the problem is with the sequence of delete statement. 看起来问题是删除语句的顺序。
Try by changing the sequence like below: 尝试更改以下序列:
public function delete()
{
$this->ptcCampaigns()->delete();
$this->ptcAds()->delete();
return parent::delete();
}
You can use Laravel's Model Events ( deleting
) to delete related models like this: 您可以使用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...
});
}
}
Hope this helps! 希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.