2016-12-09 8 views
0

verfolgen Ich habe zwei Modelle mit einer einfachen 1-n-Beziehung (Kategorie und Artikel mit category_id). Ich würde gerne zeigen, wie viele Artikel es in der Kategorie gibt. Ich hätte gerne die Zahl zwischengespeichert, anstatt immer die Zählung durchzuführen, also habe ich ein zusätzliches Feld in der Kategorietabelle "total_items_count". Wie man diese Total-Count-Auslösung am besten macht, wenn man die Funktion "countUpdate" aufruft, da sich die Beziehung von mehreren Stellen (Backend, API, Frontend ...) ändern kann.Wie Änderungen der Beziehung zwischen zwei Modellen in yii2

Mein ursprünglicher Plan war, das AFTER_UPDATE-Ereignis zu verwenden, aber "link()" muss aufgerufen werden, nachdem das Element in der Datenbank gespeichert wurde (wenn mindestens ein neues Element hinzugefügt wird), dann weiß ich nicht, welcher Kategorie das Element zugeordnet ist . Ich muss auch die alte Kategorie kennen, falls der Gegenstand von einer Kategorie in eine andere geht. Im Backend-Controller verwende ich $ item-> link ('category', $ categoryObj); wie ich diese Beziehung irgendwann zu n-n ändern könnte.

Gibt es Ratschläge, wie Sie die vollständige Kontrolle über die Änderung der Verknüpfung zwischen Artikel und Kategorie erhalten und dann die Anzahl der alten und neuen verknüpften Kategorien aktualisieren? Danke

Antwort

0

Die erste und wichtigste Sache, die Sie jetzt brauchen, ist, dass Sie das Kategorieanzahlfeld über die ActiveRecord::updateCounters() Methode aktualisieren müssen, um falsche Aktualisierung von mehreren Plätzen zu verhindern. So können Sie eines dieser Dinge tun:

In der Kategorie Artikel Modell Sie folgendes tun:

public function save($runValidation = true, $attributeNames = null) 
{ 
    if (parent::save(runValidation, attributeNames)) { 
     $this->category->updateCounters(['total_items_count' => 1]); 
     return true; 
    } 
    return false; 
} 

Oder können Sie eine zentrale Komponente schreiben (lassen Sie uns app \ Komponenten sagen \ Kategorie) der Sie Anruf von der ganzen Anwendung. Diese Komponente verfügt über eine Methode zum Speichern eines Elements. Zum Beispiel:

public function saveItem($category, $item) 
{ 
    if ($item->save()) { 
     $item->link('category', $category); 
     $category->updateCounters(['total_items_count' => 1]); 
     return true; 
    } 
    return false; 
} 

Natürlich, wenn Sie ein Element löschen, rufen Sie:

$category->updateCounters(['total_items_count' => -1]); 

See the ActiveRecord::updateCounters() API

Von der Yii2 Dokumentation:

Hinweis: Wenn Sie Verwenden Sie yii \ db \ ActiveRecord :: save(), um eine Zählerspalte zu aktualisieren. Dies kann zu ungenauen Ergebnissen führen, da es sich wahrscheinlich um sa handelt Der Zähler wird durch mehrere Anfragen gespeichert, die den gleichen Zählerwert lesen und schreiben.

Wenn Sie verfolgen, welche halten müssen die alte Kategorie ist, erstellen Sie einfach eine andere Spalte sagen wir mal „old_category“ in die Kategorie Postentabelle und wenn Sie die Kategorie des Elements der alten Kategorie-ID dort gesetzt ändern, und Die neue Kategorie-ID in der Spalte category_id.

Hilft das? Wenn Sie Fragen haben, fragen Sie bitte!

+0

Danke, ich werde es diese Woche testen. Wird save() nur aufgerufen, wenn das Element aktualisiert wird (oder sowohl beim Aktualisieren als auch beim Erstellen des Elements)? – Dakipro

+0

save() wird in beiden Fällen aufgerufen. So können Sie prüfen, ob Sie einen Artikel erstellen oder aktualisieren. Wenn Sie einen Artikel aktualisieren, ist es nicht erforderlich, den Wert total_items_count zu aktualisieren. Sie können auch die afterSave-Methode verwenden, die einen $ insert-Parameter hat, der "true" ist, wenn das Element erstellt wird. Vergiss nicht, danach parent :: afterSave() aufzurufen! –

+0

danke, ich komme jetzt näher.Die Sache ist, dass ich nicht feststellen kann, ob die Kategorie geändert wird, weil ich das Item-Modell speichern und dann "verknüpfen" muss. '$ model = $ this-> findModel ($ id); if ($ model-> load (Yii :: $ app-> Anfrage-> Post())) { $ model-> save(); // und dann verknüpfen Sie es $ Modell-> Link ('Kategorie', $ KategorieObj); ' und save() wird dann zweimal aufgerufen, und in beiden Fällen weiß ich nicht, ob" category "geändert wird ($ this-> isAttributeChanged ('category') gibt immer false zurück) – Dakipro

Verwandte Themen