2012-10-24 10 views
5

Ich habe drei Modelle, Benutzer, Kommentare und Seiten.Wie kann ich die 'enthalten Anfragen in CakePHP minimieren?

Benutzerhat vieleKommentare und KommentarezuSeiten gehören.

Alle Modelle verwenden das Verhalten containable und den Standardwert recursive -1.

Wenn ich eine find() Abfrage Kommentare rufen, mit dem enthalten Anfrage einschließlich der Seite Bereich des Modells, das korrekt gibt die Ergebnisse einer einzigen Abfrage verwenden, automatisch die Seite Tabelle für den Benutzer verbindet.

Wenn ich eine ähnliche Abfrage aus dem Benutzer Modell nennen (enthaltenKommentar und Comment.Page), ist das Ergebnis eine Abfrage, um die Kommentare, die von einer Abfrage pro Kommentar gefolgt beziehen zu Quelle der entsprechenden Seite.

Gibt es eine Möglichkeit, die Modelle zu konfigurieren, um die Optimierung JOIN zu halten? Ich nahm die belongsTo Erklärung über das verwandte Modell (Kommentare) zum Host-Modell folgen würde durch (Benutzer).

UPDATE

ich sollte klarstellen, hat meine Frage eine vereinfachte Version meiner aktuellen Fallstudie. Obwohl die Minimallösung I Modell dieser anfänglichen würde erfordernhasManyModellbelongsToModell Struktur, suche ich auch für die Lösung an einem oder mehreren zusätzlichen belongsToModelle unten in der Kette (die Würde ich automatisch LINKE VERBINDUNGEN verwenden, da dies machbar wäre).

Antwort

1

So werden Sie gefragt, ob es ein einfacher Weg ist, einfach alle Ihre Fragen enthalten? Wenn Sie alles innerhalb des aktuellen Controllers enthalten möchten. Sie könnten contain im Aufruf von beforeFilter() ausführen und auf alle Abfragen in diesem Controller anwenden.

+1

Hallo Colby. Hast du in der Praxis ein Beispiel dafür? Ich denke, dieser Ansatz kann sowohl bei einem meiner eigenen Projekte als auch beim Original-Poster helfen. –

+0

Ich glaube, so etwas in Ihrem Controller würde Ihre Abfragen für den gesamten Controller enthalten. 'Funktion beforeFilter() \t { \t \t Eltern :: beforeFilter(); \t \t $ this-> Modell-> contain ('RelatedModelStuff'); \t \t \t} // beforeFilter' –

+0

Danke Colby, das ist nicht ganz das, was ich suchte, aber der beforeFilter enthält Deklaration ist ein nützlicher Schnipsel, Prost. – Rhys

1

ich nicht ganz sicher bin, ob ich verstehe Ihre Frage, aber ich denke, Sie für den Kommentar ein Problem mit den vielen SQL-Anrufen -> Verknüpfung Seite?Wenn das richtig ist, dann

  1. versuchen linkable behaviour die fast SQL-Anrufe und arbeitet reduziert so enthält
  2. oder wenn sie so ziemlich die gleichen Daten, die Sie wollen, dann eine Funktion in einem bestimmten Modell erstellen, von wo Sie sind glücklich mit hte sQL-Aufrufe (zum Beispiel das Kommentar-Modell) und aus dem Benutzermodell aufrufen, indem $this->Comment->myFindFct($params);

Hoffnung, die

EDIT hilft: eine Sache, die mir in den Sinn kommt. Sie waren in der Lage, den Join-Typ in der Association-Array zu inner, die Torte zu Einzelanruf das zugehörige Modell auch

2

Hmm das ist interessant, zu ändern. Das ist eine Art von Optimierung, die im Kern umgesetzt werden sollte :)

Auf jeden Fall denke ich, Sie die gleichen Ergebnisse erhalten könnte (vielleicht anders formatiert) durch den Bau der Abfrage ein wenig anders:

$this->User->Comment->find('all', array(
    'conditions' => array(
    'Comment.user_id' => $userId 
), 
    'contain' => array(
    'User', 
    'Page' 
) 
)); 

Bei der Suche im Kommentarmodell sollten zwei linke Joins verwendet werden, um die Daten zu verknüpfen, da sie beide 1: 1-Beziehungen sind. Hinweis: Das Ergebnis-Array sieht möglicherweise etwas anders aus als bei der Suche im Benutzermodell.

+0

Danke jeremyharris. Das würde funktionieren, aber ich musste meine obige Frage klären, um zu zeigen, dass die reale Fallstudie mehr Ebenen von Zugehörigkeiten erfordert. Ich werde dies jedoch als eine Möglichkeit im Hinterkopf behalten, wenn ich meine Abfragen manuell erstellen muss, wird dies ein wenig Zeit sparen. – Rhys

1

Ich finde eine gute Möglichkeit, dies zu tun, ist eine custom find method zu erstellen.

Als Beispiel würde ich eine Methode in Ihrem Benutzermodell namens _findUserComments() erstellen. Sie würden dann alle Joins, Contes usw. in dieser Methode ausführen. Dann in Ihrem Controller, egal wo Sie müssen alle Ihre Benutzer-Kommentare zu erhalten, würden Sie es thusly nennen:

$this->User->find('UserComments', array(
    "conditions" => array(
     'User.id' => $userId 
    ) 
)); 

Ich hoffe, das hilft.

+0

Danke Rob. Ich benutze benutzerdefinierte Suchmethoden ziemlich umfassend, sie sind nützlich, aber das würde immer noch nicht die Situation des Erstellens extrem manueller Versionen der Abfrage (Joins, etc) umgehen, um zu erreichen, was ich verstehen würde, würde automatisch durch den Kern optimiert werden. – Rhys

1

Wenn Modelldefinition wie unten:

  1. Kommentar Modell zu Seite und Benutzer gehört.
  2. Seite gehört zum Benutzer und hat viele Kommentare.
  3. Benutzer hat viele Seite und

Code unten Kommentar wird eine Rückkehr Abfrage beigetreten:

$this->loadModel('Comment'); 
$this->Comment->Behaviors->attach('Containable'); 
$queryResult = $this->Comment->find('all', array(
    'contain' => array(
     'User', 
     'Page' 
    ) 
)); 

Der Code unten wird zwei Abfrage zurück. Seite und Benutzer traten in eine Abfrage und alle Kommentare in einer anderen Abfrage

$this->loadModel('Page'); 
$this->Page->Behaviors->attach('Containable'); 
$queryResult = $this->Page->find('all', array(
    'contain' => array(
     'User', 
    'Comment' 
    ) 
)); 

und auch unten Code wird wieder drei Abfrage, ein für jedes Modell:

$this->loadModel('User'); 
$this->User->Behaviors->attach('Containable'); 
$queryResult = $this->User->find('all', array(
    'contain' => array(
     'Page', 
     'Comment' 
    ) 
)); 
+0

Vielen Dank, obwohl die Sorge, die ich habe, für eine Modellstruktur ist, die mehrere progitTo-Verbindungen in der Kette hat, anstatt ein Modell, das zu zwei verschiedenen Modellen gehört. Z.B. Zurückgeben einer einzelnen Abfrage, in der Model1 zu Model2 gehört, Model2 zu Model3 und Model3 zu Model4. Die Daten können in einer einzigen Abfrage unter Verwendung einer benutzerdefinierten Anweisung zurückgegeben werden, aber nach meinem Verständnis sollte der Kern diese Optimierung trotzdem behandeln. – Rhys

+0

Es tut mir leid, wenn ich Ihre Aussage hier nicht verstehe. Aber zu Ihrer Frage "Benutzer hat viele Kommentare und Kommentare gehören zu Seiten" entspricht meiner obigen Modelldefinition (siehe Punkt 3 und 1). Und das Abfrageergebnis, wenn Sie vom Benutzermodell aufrufen, wurde optimiert, indem Sie einfach drei Abfragen zurückgeben (nicht wiederholt auf Seite pro Kommentar abfragen). – Habibillah

+0

Entschuldigung, ich denke, mein update klärte die tiefer gehende Fallstudie (von angeketteten equitTos), als ich erkannte, dass die Lösung der ursprünglichen Fallstudie lösbar wäre, ohne den Kontext meiner Frage abzudecken – Rhys

Verwandte Themen