Neueste Populär Trending
Laravel Lazy Eager Loading in OctoberCMS Plugins

» Laravel Lazy Eager Loading in OctoberCMS Plugins

Als ich letztens das Most Visited Plugin auf Informatik-Ninja eingebaut habe und damit eine Seite mit den beliebtesten Beiträgen zu erstellen, habe ich natürlich den Component View an das Theme überschrieben, um ihn an das Theme anzupassen. Denn zusätzlich zu den einfach Infos über den Beitrag wollte ich auch noch die Blog Kategorien und Anzahl der Besucher anzeigen lassen. Wie ich aber feststellen musste, lädt das Plugin diese nicht per Eager Loading (auch nicht die Besucherzahl, die das Plugin selbst bereitstellt), sodass diese per Lazy Loading geladen werden. Das ist natürlich auf einer Seite die mehrere Beiträge anzeigt nicht optimal, da wir hier dann das N + 1 query problem haben. Ich zitiere hier mal die Laravel Dokumentation dazu:

When accessing Eloquent relationships as properties, the relationship data is "lazy loaded". This means the relationship data is not actually loaded until you first access the property. However, Eloquent can "eager load" relationships at the time you query the parent model. Eager loading alleviates the N + 1 query problem.

In meinem Fall heißt dies also, dass für jeden Post 2 extra Abfragen ausgeführt werden. Einmal um die Kategorien zu laden und einmal um den View-Count, das heißt die Anzahl der Besucher zu bestimmen. Für eine Seite auf der die 10 beliebtesten Beiträge angezeigt werden sollen, heißt das also, dass 20 zusätzliche Abfragen notwendig wäre - das ist alles andere als optimal oder gar performant.

OctoberCMS: Laravel Lazy Loading von Relationen

OctoberCMS: Laravel Lazy Loading von Relationen

Die Frage ist jetzt: Wie kann ich erreichen, dass die Kategorien und der ViewCount per Eager Loading geladen werden und nicht per Lazy Loading. Mir sind zwei Ideen gekommen die ich euch hier vorstellen will, wobei ich letztere auch auf Informatik-Ninja einsetze.

Naive Variante: Plugin ändern

Die naive variante wäre, das man im OctoberCMS Plugin an der richtigen stelle die zusätzlich benötigen Eloquent Relation per with hinzufügt. Das ist aber nicht wirklich ratsam, da die eigenen Änderungen bei jedem Update überschrieben werden. Wenn das Plugin öffentlich ist, kann man eventuell die Laravel Eloquent Relationships per with laden, welche das Plugin eh als Abhängigkeit hat und das ganze als Pull Request veröffentlichen. Allerdings ist hier nicht sicher ob der Request akzeptiert wird und für Relationen aus anderen Plugins ist das nicht anwendbar/sinnvoll.

Schlaue Variante: Lazy Eager Loading

Mit Laravel Lazy Eager Loading kann man nachträglich Relationen per Eager Loading laden, nachdem die Daten des Models schon geladen wurdem. Wir können hier also das Plugin unberührt lassen, da wir die nötigen Relationen nachträglich im Component View laden können. Um dies nicht im Template mit Twig zu realisieren, können wir die onEnd Funktion des OctoberCMS Seiten-Lebenszyklus nutzen. Hier greifen wir auf die jeweilige Komponente und dann auf das Model/Collection zu, um dadrauf dann per Lazy Eager Loading die Relationen zu laden.

Beispiel:

In meinem oben genannten Anwendungsfall soll also auf die topPosts Komponente zugegriffen werden und die mostVisitedPosts sollen die categories und visits einmalig laden. Ich füge also auf meiner Beliebt-Seite im Code Abschnitt folgendes ein:

function onEnd() {
    // Load Post relations to reduce number of queries
    $this->page->components['topPosts']->mostVisitedPosts->load(['categories', 'visits']);
}

OctoberCMS: Laravel Lazy Eager Loading von Relationen

Jetzt werden nicht mehr 2 Abfragen pro Post benötigt, sondern nur noch 2 Abfragen (eine für die Kategorien und eine für die Besucheranzahl) -> Bei 10 Posts spare ich mir also satte 18 Datenbankabfragen!

Fazit

Sollte euch bisher noch unbekannt gewesen sein, dass etwas wie Laravel Lazy Eager Loading unterstützt, dann müsst ihr das unbedingt in der Dokumentation nachlesen. Auch der OctoberCMS Seiten-Lebenszyklus ist ein sehr nützliches Tool, um OctoberCMS und Plugins an das gewünschte Verhalten anzupassen.

Kommentar hinzufügen

Wir verwenden Cookies um Inhalte zu personalisieren und unsere Besucherstatistik zu führen. Bitte entscheiden Sie sich, ob Sie unsere Cookies akzeptieren möchten.