2016-11-16 65 views
1

我有三個模型,Advertiser,PtcAdPtcCampaign。當刪除廣告商我想要刪除所有相關的PtcAdsPtcCampaigns。該廣告有很多PtcCampaigns通過PtcAds使用Laravel的Eloquent刪除hasManyThrough relatioship行

廣告模式

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()測試失敗,爲什麼?

我有更多的測試,以確保所有關係工作,所以我真的不知道什麼可能是錯誤的。我的下一個嘗試是在廣告客戶的delete()方法中製作foreach,但也許有一些更簡單的方法,我想了解爲什麼這種方法無效。

回答

1

看起來問題在於刪除語句的順序。

嘗試通過改變像下面的順序:

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

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

    return parent::delete(); 
} 
+0

這就行了!謝謝!現在我有另一個相關的問題,因爲'PtcAd'模型具有設置爲刪除關係中的'PtcCampaign'的'delete()'方法,爲什麼我需要調用'$ this-> ptcCampaigns() - > delete ();'從'Advertiser'模型?它不應該鏈嗎? – DanVeira

+1

當你執行'$ this-> ptcAds() - > delete()'時,它會創建查詢並刪除行,以便調用delete函數查詢構建器類。但是,如果您使用'foreach'刪除'ptcAds',那麼它會調用Model類的刪除函數,並且還會刪除'ptcCampaigns'。 –

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

希望這有助於!