/** * Saves a foreign relationship where a column on another object references the id for the supplied object. * * Used to save the "many" side of a one-to-many relationship. * * Missing objects will be deleted by default. * * @param DataObjectInterface[] $objects * @param string $className Class name of foreign objects to load * @param string $foreignObjectGetter Name of getter to retrieve foreign objects * @param string $foreignColumn Property on foreign object that relates to this object id * @param boolean $deleteMissing Set to false to leave objects alone if missing */ public function saveMany(array $objects, $className, $foreignObjectGetter = null, $foreignColumn = null, $deleteMissing = true) { if (empty($objects)) { return; } if (!$foreignObjectGetter) { $foreignObjectGetter = 'get' . $this->inflector->methodNameFromClass($className, true); } if (!$foreignColumn) { $foreignColumn = $this->inflector->idColumnFromClass(get_class(reset($objects))); } $objectIdSetter = 'set' . ucfirst($foreignColumn); if ($deleteMissing) { $existingForeignIdsByObjectId = $this->getExistingForeignIds($objects, $className, $foreignColumn); } $foreignObjectsToSave = []; $foreignIdsToDelete = []; foreach ($objects as $object) { if (!method_exists($object, $foreignObjectGetter)) { throw new MethodNotImplementedException("{$foreignObjectGetter} must be defined on {$object->getClassName()} to save relationship"); } $existingForeignIds = []; if ($deleteMissing) { if (isset($existingForeignIdsByObjectId[$object->getId()])) { $existingForeignIds = $existingForeignIdsByObjectId[$object->getId()]; } } /** @var DataObjectInterface[] $foreignObjects */ $foreignObjects = $object->{$foreignObjectGetter}(); if (!empty($foreignObjects)) { if (!is_array($foreignObjects)) { throw new MethodNotImplementedException("{$foreignObjectGetter} on {$object->getClassName()} must return an array to save relationship"); } foreach ($foreignObjects as $foreignObject) { if (!method_exists($foreignObject, $objectIdSetter)) { throw new MethodNotImplementedException("{$objectIdSetter} must be defined on {$foreignObject->getClassName()} to save relationship"); } $foreignObject->{$objectIdSetter}($object->getId()); $foreignObjectsToSave[] = $foreignObject; if ($deleteMissing && $foreignObject->getId()) { unset($existingForeignIds[$foreignObject->getId()]); } } } foreach ($existingForeignIds as $id => $true) { $foreignIdsToDelete[] = $id; } } $this->objectMapper->unitOfWork()->executeTransaction(function () use($foreignObjectsToSave, $deleteMissing, $className, $foreignIdsToDelete) { $this->objectMapper->saveAll($foreignObjectsToSave); if ($deleteMissing) { $foreignObjectsToDelete = $this->objectMapper->findByIds($className, $foreignIdsToDelete); $this->objectMapper->deleteAll($foreignObjectsToDelete); } }); }
/** * 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 = []; }