2016-11-16 5 views
1

Ich habe drei Modelle, Advertiser, PtcAd und PtcCampaign. Beim Löschen eines Inserenten möchte ich alle zugehörigen PtcAds und PtcCampaigns löschen. Der Inserent hat viele PtcCampaigns bis PtcAds.Löschen hasManyThrough Reliathip Zeilen mit Laravel's Eloquent

Advertiser Modell

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 Modell

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 Modell

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

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

Die $this->assertFalse(PtcCampaign::all()->contains($ptcCampaign)) im test_delete_advertiser() Test fehlschlägt, warum?

Ich habe mehr Tests, um sicherzustellen, dass alle Beziehungen funktionieren, so dass ich wirklich nicht weiß, was möglicherweise falsch sein könnte. Mein nächster Versuch wäre, foreach in der Delete() - Methode des Advertisers zu machen, aber vielleicht gibt es etwas einfacheres und ich möchte verstehen, warum das nicht funktioniert.

Antwort

1

Es sieht aus, dass das Problem mit der Sequenz der Löschanweisung ist.

Versuchen durch die Sequenz wie unten verändert sich:

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

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

    return parent::delete(); 
} 
+0

, dass es funktioniert! Vielen Dank! Nun habe ich eine andere verwandte Frage, da das 'PtcAd'-Modell die 'delete()' Methode hat, um 'PtcCampaign' in der Beziehung zu löschen, warum muss ich' $ this-> ptcCampaigns() -> delete aufrufen(); 'aus dem' Advertiser'-Modell? Sollte es nicht ketten? – DanVeira

+1

Wenn Sie '$ this-> ptcAds() -> delete()' es erstellt Abfrage und löschen Sie die Zeilen, so dass es die 'delete 'Funktion Query Builder-Klasse aufruft. Aber wenn Sie 'ptcAds' mit' foreach' löschen, ruft es die delete-Funktion der Model-Klasse auf und löscht auch die 'ptcCampaigns'. –

1

Sie Laravel Modell Events (deleting) können ähnliche Modelle wie diese löschen:

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

hoffe, das hilft!