Doctrine2 Subquerys und der IDENTITY Helfer

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.

Neu anlegen von vorhanden Entities by ManyToOne Relationen, obwohl Entity bereits existiert

Heute bin ich auf ein im ersten Moment doch sehr seltsames Verhalten von Doctrine2 gestoßen. Benutzt man verschiedene Entity Manager innerhalb einer Applikation, so beispielsweise bei einer ManyToOne Relation versucht das hinzugefügte Entity neu anzulegen

  /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="user")
     * @ORM\JoinColumn(name="userid", referencedColumnName="id")
     */
    protected $createdFrom;

Ursache sind wie bereits erwähnt die beiden verschiedenen EntityManager Instanzen. Abhilfe schafft hier logischerweiße das verwenden von der gleichen Instanz, oder aber das Entity aus dem EntityManger neu zu laden mit dem der Speichervorgang durchgeführt werden soll. Wichtig ist jedoch hier zu beachten, das man keine inkonsistenzen schafft wenn man beide EntityManager verwendet!

Anbei noch der Link zu den Stackoverflow Beitrag, der mir hier weitergeholfen hat.

Scroll to top