. */ namespace Doctrine\ORM\Persisters; use Doctrine\ORM\PersistentCollection; /** * Persister for many-to-many collections. * * @author Roman Borschel * @since 2.0 */ class ManyToManyPersister extends AbstractCollectionPersister { /** * {@inheritdoc} * * @override */ protected function _getDeleteRowSQL(PersistentCollection $coll) { $mapping = $coll->getMapping(); $joinTable = $mapping['joinTable']; $columns = $mapping['joinTableColumns']; return 'DELETE FROM ' . $joinTable['name'] . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?'; } /** * {@inheritdoc} * * @override * @internal Order of the parameters must be the same as the order of the columns in * _getDeleteRowSql. */ protected function _getDeleteRowSQLParameters(PersistentCollection $coll, $element) { return $this->_collectJoinTableColumnParameters($coll, $element); } /** * {@inheritdoc} * * @override */ protected function _getUpdateRowSQL(PersistentCollection $coll) {} /** * {@inheritdoc} * * @override * @internal Order of the parameters must be the same as the order of the columns in * _getInsertRowSql. */ protected function _getInsertRowSQL(PersistentCollection $coll) { $mapping = $coll->getMapping(); $joinTable = $mapping['joinTable']; $columns = $mapping['joinTableColumns']; return 'INSERT INTO ' . $joinTable['name'] . ' (' . implode(', ', $columns) . ')' . ' VALUES (' . implode(', ', array_fill(0, count($columns), '?')) . ')'; } /** * {@inheritdoc} * * @override * @internal Order of the parameters must be the same as the order of the columns in * _getInsertRowSql. */ protected function _getInsertRowSQLParameters(PersistentCollection $coll, $element) { return $this->_collectJoinTableColumnParameters($coll, $element); } /** * Collects the parameters for inserting/deleting on the join table in the order * of the join table columns as specified in ManyToManyMapping#joinTableColumns. * * @param $coll * @param $element * @return array */ private function _collectJoinTableColumnParameters(PersistentCollection $coll, $element) { $params = array(); $mapping = $coll->getMapping(); $isComposite = count($mapping['joinTableColumns']) > 2; $identifier1 = $this->_uow->getEntityIdentifier($coll->getOwner()); $identifier2 = $this->_uow->getEntityIdentifier($element); if ($isComposite) { $class1 = $this->_em->getClassMetadata(get_class($coll->getOwner())); $class2 = $coll->getTypeClass(); } foreach ($mapping['joinTableColumns'] as $joinTableColumn) { if (isset($mapping['relationToSourceKeyColumns'][$joinTableColumn])) { if ($isComposite) { $params[] = $identifier1[$class1->fieldNames[$mapping['relationToSourceKeyColumns'][$joinTableColumn]]]; } else { $params[] = array_pop($identifier1); } } else { if ($isComposite) { $params[] = $identifier2[$class2->fieldNames[$mapping['relationToTargetKeyColumns'][$joinTableColumn]]]; } else { $params[] = array_pop($identifier2); } } } return $params; } /** * {@inheritdoc} * * @override */ protected function _getDeleteSQL(PersistentCollection $coll) { $mapping = $coll->getMapping(); $joinTable = $mapping['joinTable']; $whereClause = ''; foreach ($mapping['relationToSourceKeyColumns'] as $relationColumn => $srcColumn) { if ($whereClause !== '') $whereClause .= ' AND '; $whereClause .= "$relationColumn = ?"; } return 'DELETE FROM ' . $joinTable['name'] . ' WHERE ' . $whereClause; } /** * {@inheritdoc} * * @override * @internal Order of the parameters must be the same as the order of the columns in * _getDeleteSql. */ protected function _getDeleteSQLParameters(PersistentCollection $coll) { $params = array(); $mapping = $coll->getMapping(); $identifier = $this->_uow->getEntityIdentifier($coll->getOwner()); if (count($mapping['relationToSourceKeyColumns']) > 1) { $sourceClass = $this->_em->getClassMetadata(get_class($mapping->getOwner())); foreach ($mapping['relationToSourceKeyColumns'] as $relColumn => $srcColumn) { $params[] = $identifier[$sourceClass->fieldNames[$srcColumn]]; } } else { $params[] = array_pop($identifier); } return $params; } }