2015-07-08 10 views
14

Ich habe 2 Modelle, die durch eine Beziehung verbunden sind, die einen zusammengesetzten Schlüssel hat - das sind Produkt und Kategorie. Ich brauche weiche Löschungen für alle Tabellen, damit die Modelle und Beziehungen bei Bedarf wiederhergestellt werden können.Soft Löschen/Trennen und Wiederherstellen/Anfügen von Beziehungen mit zusammengesetzten Schlüsseln

In meinem Produktmodell ich habe:

function categories() 
{ 
    return $this->belongsToMany('App\Category', 'product_categories')->whereNull('product_categories.deleted_at')->withTimestamps(); 
} 

In meiner Kategorie Modell ich habe:

function products() 
{ 
    return $this->belongsToMany('App\Product', 'product_categories')->whereNull('product_categories.deleted_at')->withTimestamps(); 
} 

lese ich an anderer Stelle über die whereNull Methode verketten, wie Abfragen wie $category->products->contains($product->id) sonst wurden die weiche Rückkehr gelöschte Beziehungen

Meine Frage ist, was ist der beste Weg zum Löschen und Wiederherstellen dieser weichen gelöschten Beziehungen? Für die Wiederherstellung, zum Beispiel habe ich versucht:

$product->categories()->restore($category_id); 

Die oben erzeugt eine SQL-Fehlermeldung, die deleted_at Feld nicht eindeutig war (weil es die Tabelle Kategorien zu product_categories verbunden).

Update - Es scheint, dass das Problem Root ist, dass die BelongsToMany-Klasse keine Soft-Löschungen unterstützt - also Anhängen, Trennen und Synchronisieren aller Löschungen durchführen. Was wäre der beste Ansatz zum Überschreiben dieser Klasse? Grundsätzlich

Antwort

5

, wird es nur ein deleted_at Feld sein und statt der Verwendung der $product->categories() Verwendung zwei benutzerdefinierte (häufig) Methoden in beiden (Product und Category) Modelle zum Beispiel können Sie ein Merkmal wie folgt erstellen:

// SoftDeletePC.php 
trait SoftDeletePC { 
    // SoftDelete 
    public function softDeleteProductCategory($productId, $categoryId) 
    { 
     \DB::table('product_categories') 
     ->where('product_id', $productId) 
     ->where('category_id', $categoryId) 
     ->update(['deleted_at' => \DB::raw('NOW()')]); 
    } 

    // Restore 
    public function restoreProductCategory($productId, $categoryId) 
    { 
     \DB::table('product_categories') 
     ->where('product_id', $productId) 
     ->where('category_id', $categoryId) 
     ->update(['deleted_at' => null]); 
    } 
} 

Dann dieses Merkmal in beiden Modellen verwenden use TraitProductCategory verwenden und das Verfahren aus beiden Modellen zum Beispiel nennen:

// App/Product.php 
class product extends Model { 
    use SoftDeletePC; 
} 

// App/Category.php 
class Category extends Model { 
    use SoftDeletePC; 
} 

Also, statt diese zu verwenden:

Product->find(1)->categories()->restore(2); 

Sie können so etwas wie folgt verwenden:

$product = Product->find(1); 

$product->softDeleteProductCategory(1, 2); // Set timestamp to deleted_at 

$product->restoreProductCategory(1, 2); // Set null to deleted_at 

Hoffnung dies für Sie arbeiten kann.

+0

Dank für die Anregung. Ich fange gerade mit Laravel an und war noch nie auf Charakterzüge gestoßen. Ihre Herangehensweise ist der, die ich mir ausgedacht habe, ähnlich - also benutzerdefinierte Methoden, um damit umzugehen. Im Idealfall möchte ich einfach, dass die Standardmethoden weiche Löschungen unterstützen - obwohl ich ehrlich gesagt nicht weiß, wie machbar das ist. Ich poste als Antwort meine eigene Version der Synchronisierung, die ich erstellt habe. – BrynJ

1

Ich habe am Ende einige benutzerdefinierte Methoden in meinem Produktmodell erstellt, um zu erreichen, was ich brauche - nicht meine ideale Lösung, aber es funktioniert trotzdem. Meine benutzerdefinierte Synchronisations sieht wie folgt aus:

class Product extends Model 
{ 
    // update relationship to categories 
    function categories_sync($category_ids) 
    { 
     // categories 
     $existing_category_ids = $this->categories()->lists('category_id')->all(); 
     $trashed_category_ids = $this->categories('onlyTrashed')->lists('category_id')->all(); 

     if(is_array($category_ids)) { 

      foreach($category_ids as $category_id) { 
       if(in_array($category_id, $trashed_category_ids)) { 
        $this->categories()->updateExistingPivot($category_id, ['deleted_at' => null]); 
       } 
       elseif(!in_array($category_id, $existing_category_ids)) { 
        $this->categories()->attach($category_id); 
       } 
      } 

      foreach($existing_category_ids as $category_id) { 
       if(!in_array($category_id, $category_ids)) { 
        $this->categories()->updateExistingPivot($category_id, ['deleted_at' => date('YmdHis')]); 
       } 
      } 
     } 
     else { 
      foreach($existing_category_ids as $category_id) { 
       $this->categories()->updateExistingPivot($category_id, ['deleted_at' => date('YmdHis')]); 
      } 
     } 
    } 
} 

Die oben beruht auf einer erweiterten Kategorien() Methode:

// relationship to categories 
function categories($trashed=false) 
{ 
    if($trashed=='withTrashed') { 
     return $this->belongsToMany('App\Category', 'product_categories')->withTimestamps(); 
    } 
    elseif($trashed=='onlyTrashed') { 
     return $this->belongsToMany('App\Category', 'product_categories')->whereNotNull('product_categories.deleted_at')->withTimestamps(); 
    } 
    else { 
     return $this->belongsToMany('App\Category', 'product_categories')->whereNull('product_categories.deleted_at')->withTimestamps(); 
    } 
} 
Verwandte Themen