Vor allem bei Suchquerys kommt man oft nicht an Subquerys vorbei. Konkretes beispielsweiße ist hier die Suche nach Einträgen mit gewissen Tags im AAUShare System. Es gibt hier das Post Entity mit den Mappings zu den Tags, bzw PostTags(Mapping zwischen Tags und Posts). Um hier z.B. alle Posts zu erhalten die mit einen Tag besitzen ist noch recht unkompliziert, möchte man jedoch nur Posts mit z.B. den Tags Informatik und ESOP so wird die Query schon komplizierter. Ich habe dazu folgende Methode implementiert:
public function findByTagTitles(array $tags, $additive){
$tagtsrings = '';
$logicalop = 'OR';
if($additive == true){
$logicalop = 'AND';
}
//create query statement ors and ands
for($i=0; $i<sizeof($tags); $i++){
$tagtsrings .= ' p.id IN (SELECT IDENTITY(pt'.$i.'.post) FROM AAUShare\Entity\PostTag pt'.$i.' JOIN pt'.$i.'.tag t'.$i.' WITH t'.$i.'.title LIKE :tag'.$i.')';
if(($i+1) < sizeof($tags)){ //last and or or
$tagtsrings .=' '.$logicalop;
}
}
if(sizeof($tags)==0){
$tagtsrings.='1';
}
//
$querystring = 'SELECT p FROM AAUShare\Entity\Post p WHERE'.$tagtsrings;
$query = $this->getEntityManager()->createQuery($querystring);
//bind
for($i=0; $i<sizeof($tags); $i++){
$query->setParameter('tag'.$i, $tags[$i]);
}
//do query
return $query->getResult();
}
Hier wird ein Array mit Tags übergeben, nach welchen gesucht wird, der zweite Parameter bestimmt ob die Tags mit „AND“ oder mit „OR“ verknüpft werden. Interessant sind hierbei vor allem die for-Schleifen. In der ersten werden die Tags in Subquerys gepackt und geprüft ob der Post in der Menge der zurückgelieferten postids vorhanden ist. Wichtig ist hierbuach der IDENTITY Befehl für Doctrine2, damit wird auf den Foreign Key der OneToMany Relation in PostTag zugegriffen. Außerdem werden die Subquerys durchnummeriert und auch damit die Parameter
In der zweiten for-Schleife werden die durchnummerierten Query Parameter noch mit den Werten aus den Tags verknüpft.