/** * Gets an association proxy instance. */ public function getAssociationProxy($owner, \Doctrine\ORM\Mapping\AssociationMapping $assoc) { $proxyClassName = str_replace('\\', '_', $assoc->getTargetEntityName()) . 'AProxy'; if (!class_exists($proxyClassName, false)) { $this->_em->getMetadataFactory()->setMetadataFor(self::$_ns . $proxyClassName, $this->_em->getClassMetadata($assoc->getTargetEntityName())); $fileName = $this->_cacheDir . $proxyClassName . '.g.php'; if (!file_exists($fileName)) { $this->_generateAssociationProxyClass($assoc->getTargetEntityName(), $proxyClassName, $fileName); } require $fileName; } $proxyClassName = '\\' . self::$_ns . $proxyClassName; return new $proxyClassName($this->_em, $assoc, $owner); }
/** * {@inheritdoc} */ public function remove($key) { // TODO: If the keys are persistent as well (not yet implemented) // and the collection is not initialized and orphanRemoval is // not used we can issue a straight SQL delete/update on the // association (table). Without initializing the collection. $this->_initialize(); $removed = $this->_coll->remove($key); if ($removed) { $this->_changed(); if ($this->_association !== null && $this->_association->isOneToMany() && $this->_association->orphanRemoval) { $this->_em->getUnitOfWork()->scheduleOrphanRemoval($removed); } } return $removed; }
/** * {@inheritdoc} */ public function clear() { if ($this->initialized && $this->isEmpty()) { return; } if ($this->association->isOneToMany() && $this->association->orphanRemoval) { foreach ($this->coll as $element) { $this->em->getUnitOfWork()->scheduleOrphanRemoval($element); } } $this->coll->clear(); if ($this->association->isOwningSide) { $this->changed(); $this->em->getUnitOfWork()->scheduleCollectionDeletion($this); $this->takeSnapshot(); } }
/** * Adds an element to the collection. * * @param mixed $value * @param string $key * @return boolean Always TRUE. * @override */ public function add($value) { parent::add($value); if ($this->_hydrationFlag) { if ($this->_backRefFieldName) { // Set back reference to owner if ($this->_association->isOneToMany()) { $this->_typeClass->getReflectionProperty($this->_backRefFieldName)->setValue($value, $this->_owner); } else { // ManyToMany $this->_typeClass->getReflectionProperty($this->_backRefFieldName)->getValue($value)->add($this->_owner); } } } else { $this->_changed(); } return true; }
/** * Gather columns and fk constraints that are required for one part of relationship. * * @param array $joinColumns * @param \Doctrine\DBAL\Schema\Table $theJoinTable * @param ClassMetadata $class * @param \Doctrine\ORM\Mapping\AssociationMapping $mapping * @param array $primaryKeyColumns * @param array $uniqueConstraints */ private function _gatherRelationJoinColumns($joinColumns, $theJoinTable, $class, $mapping, &$primaryKeyColumns, &$uniqueConstraints) { $localColumns = array(); $foreignColumns = array(); $fkOptions = array(); foreach ($joinColumns as $joinColumn) { // Note that this thing might be quoted, i.e. `foo`, [foo], ... $columnName = $mapping->getQuotedJoinColumnName($joinColumn['name'], $this->_platform); $referencedFieldName = $class->getFieldName($joinColumn['referencedColumnName']); if (!$class->hasField($referencedFieldName)) { throw new \Doctrine\Common\DoctrineException("Column name `" . $joinColumn['referencedColumnName'] . "` referenced for relation from " . "{$mapping->sourceEntityName} towards {$mapping->targetEntityName} does not exist."); } $primaryKeyColumns[] = $columnName; $localColumns[] = $columnName; $foreignColumns[] = $joinColumn['referencedColumnName']; if (!$theJoinTable->hasColumn($joinColumn['name'])) { // Only add the column to the table if it does not exist already. // It might exist already if the foreign key is mapped into a regular // property as well. $fieldMapping = $class->getFieldMapping($referencedFieldName); $columnDef = null; if (isset($joinColumn['columnDefinition'])) { $columnDef = $joinColumn['columnDefinition']; } else { if (isset($fieldMapping['columnDefinition'])) { $columnDef = $fieldMapping['columnDefinition']; } } $columnOptions = array('notnull' => false, 'columnDefinition' => $columnDef); if (isset($joinColumn['nullable'])) { $columnOptions['notnull'] = !$joinColumn['nullable']; } $theJoinTable->createColumn($columnName, $class->getTypeOfColumn($joinColumn['referencedColumnName']), $columnOptions); } if (isset($joinColumn['unique']) && $joinColumn['unique'] == true) { $uniqueConstraints[] = array('columns' => array($columnName)); } if (isset($joinColumn['onUpdate'])) { $fkOptions['onUpdate'] = $joinColumn['onUpdate']; } if (isset($joinColumn['onDelete'])) { $fkOptions['onDelete'] = $joinColumn['onDelete']; } } $theJoinTable->addUnnamedForeignKeyConstraint($class->getQuotedTableName($this->_platform), $localColumns, $foreignColumns, $fkOptions); }
/** * Stores the association mapping. * * @param AssociationMapping $assocMapping */ private function _storeAssociationMapping(AssociationMapping $assocMapping) { $sourceFieldName = $assocMapping->getSourceFieldName(); if (isset($this->associationMappings[$sourceFieldName])) { throw MappingException::duplicateFieldMapping(); } $this->associationMappings[$sourceFieldName] = $assocMapping; $this->_registerMappingIfInverse($assocMapping); // Store ReflectionProperty of mapped field $refProp = $this->reflClass->getProperty($sourceFieldName); $refProp->setAccessible(true); $this->reflFields[$sourceFieldName] = $refProp; }
/** * INTERNAL: * Sets the collection owner. Used (only?) during hydration. * * @param object $entity * @param AssociationMapping $assoc */ public function setOwner($entity, AssociationMapping $assoc) { $this->_owner = $entity; $this->_association = $assoc; if ($assoc->isInverseSide()) { // For sure bi-directional $this->_backRefFieldName = $assoc->mappedByFieldName; } else { $targetClass = $this->_em->getClassMetadata($assoc->targetEntityName); if (isset($targetClass->inverseMappings[$assoc->sourceFieldName])) { // Bi-directional $this->_backRefFieldName = $targetClass->inverseMappings[$assoc->sourceFieldName]->sourceFieldName; } } }