Удалите строки отношений hasManyThrough, используя Eloquent от Laravel

У меня есть три модели, Advertiser, PtcAd, а также PtcCampaign, При удалении рекламодатель Я хочу удалить все связанные PtcAds а также PtcCampaigns. рекламодатель имеет много PtcCampaigns через PtcAds.

Модель рекламодателя

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

$this->assertFalse(PtcCampaign::all()->contains($ptcCampaign)) в test_delete_advertiser() тест не пройден, почему?

У меня есть больше тестов, чтобы убедиться, что все отношения работают, поэтому я действительно не знаю, что может быть не так. Моя следующая попытка будет сделать foreach в методе delete () рекламодателя, но, возможно, есть что-то более простое, и я хочу понять, почему это не работает.

1

Решение

Похоже, проблема в последовательности оператора удаления.

Попробуйте изменить последовательность, как показано ниже:

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

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

return parent::delete();
}
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...
});
}
}

Надеюсь это поможет!

1

По вопросам рекламы [email protected]