2016-12-05 3 views
0

Ich versuche eine Auswahl basierend auf mehreren IDs in Joins zu treffen, jede der IDs sollte mit einer anderen Bedingung eines anderen Joins übereinstimmen.Doctrine Auswahl von Joins basierend auf mehreren Bedingungen

Ich brauche "Typen", die alle "Dichotomien" in "Position" 1 oder 2 haben. Im Moment gibt es Ergebnisse, die einer der Dichotomien entsprechen, die an die Funktion übergeben wurden, aber nicht alle.

$QB->select("Types","Types,ElementsPositions, Elements, Positions, Dichotomies, Quadras,TypesDescriptions,Relations") 
       ->from($this->get_repository()[0], 'Types'); 
       $QB->leftJoin("Types.ElementsPositions","ElementsPositions", \Doctrine\ORM\Query\Expr\Join::WITH, 'ElementsPositions.Positions = 1 OR ElementsPositions.Positions = 2'); 
       $QB->leftJoin("ElementsPositions.Elements","Elements"); 
       $QB->leftJoin("ElementsPositions.Positions","Positions"); 
       $QB->leftJoin("Elements.Dichotomies","Dichotomies"); 
       $QB->leftJoin("Types.Quadras","Quadras"); 
       $QB->leftJoin("Types.TypesDescriptions","TypesDescriptions"); 
       $QB->leftJoin("Types.Relations","Relations"); 

    if(!empty($where['dichotomies'])){ 
     foreach($where['dichotomies'] as $dichotomy){ 
       $QB->andWhere('Dichotomies.id'.'=:dichotomy'); 
       $QB->setParameter('dichotomy', $dichotomy['id']);     
     }    
    } 

UPD. Tabellen-Mapping - in JSON:

{ 
"table-name": "types",  
"joins":[ 
    { 
     "table-name":"elements_positions", 
     "type":"one-to-many" 
    }, 
    { 
     "table-name":"quadras", 
     "type":"many-to-one" 
    }, 
    { 
     "table-name":"types_descriptions", 
     "type":"one-to-one" 
    }, 
    { 
     "table-name":"relations", 
     "type":"many-to-one" 
    } 
]} 

Elemente Positionieren

{ 
    "table-name": "elements_positions", 
    "joins":[ 
     { 
      "table-name":"elements", 
      "type":"many-to-one" 
     }, 
     { 
      "table-name":"positions", 
      "type":"many-to-one" 
     }, 
     { 
      "table-name":"types", 
      "type":"many-to-one" 
     } 
    ] 
} 

Element

{ 
     "table-name": "elements",  
     "joins":[ 
      { 
       "table-name":"elements_positions", 
       "type":"one-to-many" 
      }, 
      { 
       "table-name":"quadras", 
       "type":"many-to-many" 
      }, 
      { 
       "table-name":"dichotomies", 
       "type":"many-to-many" 
      } 
     ] 
    } 

Positionen

"table-name": "positions",  
    "joins":[ 
     { 
      "table-name":"elements_positions", 
      "type":"one-to-many" 
     } 
    ] 
} 

Dichotomies:

{ 
    "table-name": "dichotomies", 
    "joins":[ 
     { 
      "table-name":"elements", 
      "type":"many-to-many-inversed" 
     } 
    ] 
} 

Antwort

1

Ihre Abfrage hat zwei verschiedene Probleme.

Zuerst werden mehrere Parameterwerte mit einem einzelnen Parameter verknüpft. Jedes nächste Element von $where['dichotomies'] ersetzt den vorherigen Wert des Parameters :dichotomy in der Abfrage. Die Methode setParameters() bindet Werte nicht wirklich an die vorbereitete Anweisung: Sie speichert sie nur im QueryBuilder-Objekt. Nach dem Ende der foreach-Schleife werden alle Bedingungen denselben Wert haben (der letzte von $where['dichotomies']). Um dies zu vermeiden, müssen Sie verschiedene Parameternamen oder numerische Indizes verwenden.

Zweitens fügen Sie Bedingungen, die widersprüchlich sind:

Dichotomies.id = :dichotomy 
AND Dichotomies.id = :dichotomy 
AND Dichotomies.id = :dichotomy 
... 

Eine Entität ID offensichtlich nicht gleichzeitig auf unterschiedliche Werte gleich

. $QB->andWhere() so etwas produzieren Sie müssen also AND durch den Operator OR ersetzen.

Aber bessere Weg ist IN Klausel zu verwenden:

setParameter() automatisch aufrufen folgert, welche Art Sie als Wert setzen. Dies funktioniert für Ganzzahlen, Arrays von Strings/Ganzzahlen, DateTime-Instanzen und für verwaltete Entitäten.

ersetzen einfach die foreach-Schleife durch die folgenden Zeilen:

$QB->andWhere('Dichotomies.id IN (:dichotomies)'); 
$QB->setParameters('dichotomies', array_column($where['dichotomies'], 'id')); 

array_column() Die Funktion gibt eine Liste von IDs aller Dichotomie. Doctrine generiert den Ausdruck IN und verwendet diese Liste, um Abfrageplatzhalter zu generieren und die Werte zu binden.

+0

Oh, ja, SetParameter() überschrieb es jedes Mal in der Tat! Aber die Dichotomies-Tabelle ist die umgekehrte Seite von Viele-zu-Viele zu Elementen, und Elemente sind eins zu viele zu ElementenPositionen, die drei Verknüpfungen hat - Typen, Elemente und Positionen.Ein Typ kann also zwei Dichotomien (über Elemente) in Position 1 und 2 haben und ich muss durch 2 $ -Dichotomien herausgefiltert werden - beide müssen in Position 1 oder 2 sein. Deshalb "und" nicht "oder". Aber das funktioniert nicht - gibt mir keine Ergebnisse mit 2 Dichotomien gesendet, und wenn ich zu "oder" ändere - gibt mir Ergebnisse, die eine der beiden übereinstimmen. –

+0

Sorry, aber es ist ein bisschen schwer zu verstehen. Können Sie Ihre Abfrage bearbeiten und eine native SQL-Abfrage bereitstellen, die Sie erhalten möchten? – Timurib

+0

Ich fürchte, wenn ich es in reinem SQL wüsste, wäre ich in der Lage zu übersetzen. Was ich versuche zu sagen, Tabelle "Typen" kann mehrere "Dichotomien" und "Dichotomien" von "Typ" haben "Positionen". Ich muss überprüfen, dass beide (2) "Dichotomien" eines "Typs" in "Positionen" 1 oder 2 sind. Bin ich konzeptionell hier falsch? –

Verwandte Themen