/**
  * Loads a collection of entities of a many-to-many association.
  *
  * @param ManyToManyMapping $assoc The association mapping of the association being loaded.
  * @param object $sourceEntity The entity that owns the collection.
  * @param PersistentCollection $coll The collection to fill.
  */
 public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
 {
     $criteria = array();
     $sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
     $joinTableConditions = array();
     if ($assoc['isOwningSide']) {
         foreach ($assoc['relationToSourceKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
             if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
                 $criteria[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
             } else {
                 throw MappingException::joinColumnMustPointToMappedField($sourceClass->name, $sourceKeyColumn);
             }
         }
     } else {
         $owningAssoc = $this->_em->getClassMetadata($assoc['targetEntity'])->associationMappings[$assoc['mappedBy']];
         // TRICKY: since the association is inverted source and target are flipped
         foreach ($owningAssoc['relationToTargetKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
             if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
                 $criteria[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
             } else {
                 throw MappingException::joinColumnMustPointToMappedField($sourceClass->name, $sourceKeyColumn);
             }
         }
     }
     $sql = $this->_getSelectEntitiesSQL($criteria, $assoc);
     $stmt = $this->_conn->executeQuery($sql, array_values($criteria));
     while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
         $coll->hydrateAdd($this->_createEntity($result));
     }
     $stmt->closeCursor();
 }
 private function getManyToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null)
 {
     $criteria = array();
     $sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
     if ($assoc['isOwningSide']) {
         $quotedJoinTable = $sourceClass->getQuotedJoinTableName($assoc, $this->_platform);
         foreach ($assoc['relationToSourceKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
             if ($sourceClass->containsForeignIdentifier) {
                 $field = $sourceClass->getFieldForColumn($sourceKeyColumn);
                 $value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
                 if (isset($sourceClass->associationMappings[$field])) {
                     $value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
                     $value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
                 }
                 $criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value;
             } else {
                 if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
                     $criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
                 } else {
                     throw MappingException::joinColumnMustPointToMappedField($sourceClass->name, $sourceKeyColumn);
                 }
             }
         }
     } else {
         $owningAssoc = $this->_em->getClassMetadata($assoc['targetEntity'])->associationMappings[$assoc['mappedBy']];
         $quotedJoinTable = $sourceClass->getQuotedJoinTableName($owningAssoc, $this->_platform);
         // TRICKY: since the association is inverted source and target are flipped
         foreach ($owningAssoc['relationToTargetKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
             if ($sourceClass->containsForeignIdentifier) {
                 $field = $sourceClass->getFieldForColumn($sourceKeyColumn);
                 $value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
                 if (isset($sourceClass->associationMappings[$field])) {
                     $value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
                     $value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
                 }
                 $criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value;
             } else {
                 if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
                     $criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
                 } else {
                     throw MappingException::joinColumnMustPointToMappedField($sourceClass->name, $sourceKeyColumn);
                 }
             }
         }
     }
     $sql = $this->_getSelectEntitiesSQL($criteria, $assoc, 0, $limit, $offset);
     list($params, $types) = $this->expandParameters($criteria);
     return $this->_conn->executeQuery($sql, $params, $types);
 }
    /**
     * @param array    $assoc
     * @param object   $sourceEntity
     * @param int|null $offset
     * @param int|null $limit
     *
     * @return \Doctrine\DBAL\Driver\Statement
     *
     * @throws \Doctrine\ORM\Mapping\MappingException
     */
    private function getManyToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null)
    {
        $sourceClass    = $this->em->getClassMetadata($assoc['sourceEntity']);
        $class          = $sourceClass;
        $association    = $assoc;
        $criteria       = array();


        if ( ! $assoc['isOwningSide']) {
            $class       = $this->em->getClassMetadata($assoc['targetEntity']);
            $association = $class->associationMappings[$assoc['mappedBy']];
        }

        $joinColumns = $assoc['isOwningSide']
            ? $association['joinTable']['joinColumns']
            : $association['joinTable']['inverseJoinColumns'];

        $quotedJoinTable = $this->quoteStrategy->getJoinTableName($association, $class, $this->platform);

        foreach ($joinColumns as $joinColumn) {

            $sourceKeyColumn    = $joinColumn['referencedColumnName'];
            $quotedKeyColumn    = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform);

            switch (true) {
                case $sourceClass->containsForeignIdentifier:
                    $field = $sourceClass->getFieldForColumn($sourceKeyColumn);
                    $value = $sourceClass->reflFields[$field]->getValue($sourceEntity);

                    if (isset($sourceClass->associationMappings[$field])) {
                        $value = $this->em->getUnitOfWork()->getEntityIdentifier($value);
                        $value = $value[$this->em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
                    }

                    break;

                case isset($sourceClass->fieldNames[$sourceKeyColumn]):
                    $field = $sourceClass->fieldNames[$sourceKeyColumn];
                    $value = $sourceClass->reflFields[$field]->getValue($sourceEntity);

                    break;

                default:
                    throw MappingException::joinColumnMustPointToMappedField(
                        $sourceClass->name, $sourceKeyColumn
                    );
            }

            $criteria[$quotedJoinTable . '.' . $quotedKeyColumn] = $value;
        }

        $sql = $this->getSelectSQL($criteria, $assoc, 0, $limit, $offset);
        list($params, $types) = $this->expandParameters($criteria);

        return $this->conn->executeQuery($sql, $params, $types);
    }