. */ 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; } }