2016-11-16 77 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... 
     }); 
    } 
} 

希望这有助于!