/** * Loads objects of the foreign class onto the supplied objects linked by a link table containing the id's of both objects * * @param DataObjectInterface[] $objects * @param string $className Class name of foreign objects to load * @param string $linkTable Table that links two objects together * @param string $idColumn Column on link table = the id on this object * @param string $foreignIdColumn Column on link table = the id on the foreign object table * @return DataObjectInterface[] Loaded objects keyed by id */ public function loadManyToMany(array $objects, $className, $linkTable, $idColumn = null, $foreignIdColumn = null) { if (empty($objects)) { return []; } $ids = DataObject::getIds($objects); $queryHelper = $this->objectMapper->getQueryHelper(); $db = $queryHelper->getConnection(); $qb = $queryHelper->buildSelectQuery($linkTable, [$db->quoteIdentifier($idColumn) . ' AS id', $db->quoteIdentifier($foreignIdColumn) . ' AS ' . $db->quoteIdentifier('foreignId')], [$idColumn => $ids]); $foreignIdsById = []; $foreignIds = []; $linkRows = $qb->execute(); $linkRows->setFetchMode(\PDO::FETCH_OBJ); foreach ($linkRows as $linkRow) { $foreignIdsById[$linkRow->id][] = $linkRow->foreignId; $foreignIds[$linkRow->foreignId] = true; } $foreignObjects = $this->objectMapper->findByIds($className, array_keys($foreignIds)); unset($foreignIds); $foreignObjectsById = []; foreach ($foreignObjects as $foreignObject) { $foreignObjectsById[$foreignObject->getId()] = $foreignObject; } unset($foreignObjects); $setter = 'set' . $this->inflector->methodNameFromColumn($foreignIdColumn, true); foreach ($objects as $object) { if (method_exists($object, $setter)) { $foreignObjects = []; if (isset($foreignIdsById[$object->getId()])) { $foreignIds = $foreignIdsById[$object->getId()]; foreach ($foreignIds as $foreignId) { $foreignObjects[] = $foreignObjectsById[$foreignId]; } } $object->{$setter}($foreignObjects); } else { throw new MethodNotImplementedException("{$setter} must be defined on {$object->getClassName()} to load many-to-many relationship with {$className}"); } } return $foreignObjectsById; }
/** * Executes all operations * * @param callable $exceptionHandler */ public function flush(callable $exceptionHandler = null) { $this->executeTransaction(function () { foreach ($this->objectsToSave as $objects) { if (count($objects) == 1) { $this->orm->save($objects[0]); } else { $this->orm->saveAll($objects); } } foreach ($this->objectsToDelete as $objects) { if (count($objects) == 1) { $this->orm->delete($objects[0]); } else { $this->orm->deleteAll($objects); } } }, $exceptionHandler); $this->objectsToSave = []; $this->objectsToDelete = []; }
public function testSaveManyToMany() { $otherObjects = []; $otherObject = new OtherDataObject(); $otherObject->setName('Other object many-to-many 1-1'); $otherObject2 = new OtherDataObject(); $otherObject2->setName('Other object many-to-many 1-2'); $otherObject3 = new OtherDataObject(); $otherObject3->setName('Other object many-to-many 2-1'); $otherObject4 = new OtherDataObject(); $otherObject4->setName('Other object many-to-many 2-2'); $otherObjectToDelete = new OtherDataObject(); $otherObjects[] = $otherObjectToDelete->setName('Other object many-to-many 1-3'); $otherObjectToDelete2 = new OtherDataObject(); $otherObjects[] = $otherObjectToDelete2->setName('Other object many-to-many 2-3'); $objects = []; $object = new ExtendedDataObject(); $object2 = new ExtendedDataObject(); $objects[] = $object->setMyColumn('Save many-to-many 1')->setOtherDataObjects([$otherObject, $otherObject2]); $objects[] = $object2->setMyColumn('Save many-to-many 2')->setOtherDataObjects([$otherObject3, $otherObject4]); $this->repository->saveAll($objects); $this->objectMapper->saveAll($otherObjects); $queryHelper = $this->objectMapper->getQueryHelper(); $queryHelper->massInsert('extended_other_rel', [['extendedDataObjectId' => $object->getId(), 'otherDataObjectId' => $otherObjectToDelete->getId()], ['extendedDataObjectId' => $object2->getId(), 'otherDataObjectId' => $otherObjectToDelete2->getId()]]); $relationshipSaver = $this->objectMapper->getRelationshipSaver(); $relationshipSaver->saveManyToMany($objects, OtherDataObject::class, 'extended_other_rel'); $this->assertGreaterThan(0, $otherObject->getId()); $this->assertGreaterThan(0, $otherObject2->getId()); $this->assertGreaterThan(0, $otherObject3->getId()); $this->assertGreaterThan(0, $otherObject4->getId()); $objectLinks = $queryHelper->buildSelectQuery('extended_other_rel', self::$connection->quoteIdentifier('otherDataObjectId'), ['extendedDataObjectId' => $object->getId()])->execute()->fetchAll(\PDO::FETCH_COLUMN); $this->assertCount(2, $objectLinks); $this->assertEquals($otherObject->getId(), $objectLinks[0]); $this->assertEquals($otherObject2->getId(), $objectLinks[1]); $object2Links = $queryHelper->buildSelectQuery('extended_other_rel', self::$connection->quoteIdentifier('otherDataObjectId'), ['extendedDataObjectId' => $object2->getId()])->execute()->fetchAll(\PDO::FETCH_COLUMN); $this->assertCount(2, $object2Links); $this->assertEquals($otherObject3->getId(), $object2Links[0]); $this->assertEquals($otherObject4->getId(), $object2Links[1]); }
/** * Retrieve foreign ids for a one-to-many relationship * * @param DataObjectInterface[] $objects * @param string $className * @param string $foreignColumn * @return array objectId => map of foreign ids */ protected function getExistingForeignIds(array $objects, $className, $foreignColumn) { $objectIds = DataObject::getIds($objects); $queryHelper = $this->objectMapper->getQueryHelper(); $foreignTable = $className::getTableName(); $foreignColumns = $queryHelper->getDbColumns($foreignTable); $criteria = [$foreignColumn => $objectIds]; if (isset($foreignColumns['isDeleted'])) { $criteria['isDeleted'] = 0; } $qb = $queryHelper->buildSelectQuery($foreignTable, ['id', $queryHelper->getConnection()->quoteIdentifier($foreignColumn)], $criteria); $existingForeignObjectIds = $qb->execute()->fetchAll(\PDO::FETCH_NUM); $existingForeignObjectsIdsByObjectId = []; foreach ($existingForeignObjectIds as $row) { list($foreignId, $objectId) = $row; if (!isset($existingForeignObjectsIdsByObjectId[$objectId])) { $existingForeignObjectsIdsByObjectId[$objectId] = [$foreignId => true]; } else { $existingForeignObjectsIdsByObjectId[$objectId][$foreignId] = true; } } return $existingForeignObjectsIdsByObjectId; }
/** * @param string $className * @param string $suffix * @return string */ protected function idColumnFromClass($className, $suffix = 'Id') { return $this->objectMapper->getInflector()->idColumnFromClass($className, $suffix); }
public function testUnitOfWork() { $connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock(); $connection->expects($this->any())->method('getDatabasePlatform')->willReturn(new MySqlPlatform()); $corma = ObjectMapper::withDefaults($connection, ['Corma\\Test\\Fixtures']); $unitOfWork = $corma->unitOfWork(); $this->assertInstanceOf(UnitOfWork::class, $unitOfWork); }