2013-08-09 4 views
8

Ich versuche ein Kriterium nach the Doctrine Docs einzurichten.Lehre 2.3 Kriterien. Zugreifen auf ein zugehöriges Objekt

Leider sagen sie Ihnen nicht, wie Sie auf Attribute eines verwandten Objekts zugreifen. Lassen Sie mich Ihnen ein Beispiel geben.

Ich habe eine ArrayCollection von Produkten. Jedes Produkt hat eine Kategorie. Ich möchte die ArrayCollection nach einem Kategorienamen filtern. Jetzt versuche ich, einen festgelegten Kriterien wie folgt zusammen:

$criteria = Criteria::create() 
    ->where(Criteria::expr()->eq("category.name", "SomeCategoryName")); 

Jetzt erhalte ich die folgende Ausnahme:

An exception has been thrown during the rendering of a template ("Unrecognized field: category.name") 

Wie kann ich ein ähnliches Objekt zugreifen?

Antwort

5

Ich schaute in den Quellcode Criteria::expr()->eq("name", --- second value ---). Der zweite Wert erwartet eine Instanz von Doctrine\Common\Collections\Expr\Value. Es ist also nicht möglich, einen anderen Expr oder criteria dort zu setzen. Nur die ExprAnd und Or nehmen eine weitere Expr. Ich bin mir ziemlich sicher, dass Sie dies mit anderen Funktionen wie filter() lösen oder einen Iterator mit getIterator() erhalten sollen. So kann es mit der Methode filter() gemacht werden.

$filteredProducts = 
    $products->filter(function($key, $element) use ($categoryName) { 
     return $element->getCategory()->getName() === categoryName; 
    }); 

Wenn Sie können ein Iterator für jede nächste Beziehung Sie nisten foreach-Schleifen und Filter in die kann.

+1

Vielen Dank für Ihre Antwort. Ich werde deine 'Ctriteria' am Montag testen. Im Moment habe ich keinen Zugriff auf meine Arbeitsstation. Ich werde Sie wissen lassen, ob es funktioniert. Aber Filter ist meiner Meinung nach eine schlechte Idee, weil alle Kategorien eifrig geladen und dann lokal auf der Platte verarbeitet werden (Was wird niemals so leistungsfähig sein, wie es in einer DB gemacht wird). – Robin

+0

Sie sind falsch informiert. Kriterien können in einer Abfrage (Daten, die abgerufen werden) sowie in einer ArrayCollection (bereits abgerufene Daten) verwendet werden. Wenn Sie keine Fetch-Joins machen, wird die Relation geladen, egal ob Sie Kriterien oder filter() verwenden. Sie haben recht, dass die DB Ihnen die meiste Leistung bringt, deshalb ist es am besten, Fetch Join in Kombination mit WHERE zu verwenden. Obwohl das nicht deine Frage war. – Flip

+0

Ich dachte, es wäre möglich, Ihre Entitäten zu kommentieren, so dass sie faul geladen sind? http: // Dokumentedoctrine-project.org/en/2.0.x/reference/annotations-reference.html#annref-manytoone. Wäre das nicht die 'ArrayCollection' faul? Oder würde das nicht funktionieren, weil das die umgekehrte Annotation ist? – Robin

2

Das gehört wahrscheinlich eher zu einer Repository-Methode als zu einer Filtermethode. Wenn Sie eine vorgefilterte Liste von Produkten in einer Sammlung für ein übergeordnetes Objekt (z. B. eine Bestellung oder etwas) abrufen möchten, können Sie die untergeordnete Sammlung im Abfrage-Generator filtern. Sie müssen sich jedoch mit der möglicherweise verwirrenden Nebenwirkung von nicht vollständig hydratisierten Objekten auseinandersetzen.

Dies sollte Ihnen eine Liste von Order Objekte geben, die nur Product Kinder einen passenden Kategorienamen haben.

class OrderRepository extends EntityRepository { 
    public function findOrderWithProductCategory($category) 
    { 
    $builder = $this->createQueryBuilder('o') 
     ->select('o, p') 
     ->leftJoin('o.products', 'p') 
     ->join('p.category', 'c', 'WITH', 'c.name = :category') 
     ->setParameter('category', $category); 
    } 
} 

Wenn Sie nicht wissen, welche Art von Kategorien sind Sie erst später interessiert, dann sind Sie wahrscheinlich besser @ Flip-Lösung unter Verwendung von wie auch immer, und Pre-feuchtigkeitsspend alle Kategorien. Mit partial hydration und Standard ArrayCollection::filter() Verschlüsse, funktioniert in den meisten Fällen ziemlich gut.

Das sagte, es wäre ziemlich nett als Feature. Ich vermute, dass die Doktrin-Leute zögerten, weil die aktuelle Implementierung sehr leicht ist und sie es wahrscheinlich so behalten wollen.

+0

tatsächlich ist dieses [Problem] (https://github.com/doctrine/collections/pull/27) bereits geöffnet: – yvoyer

Verwandte Themen