Дело немного сложнее. У меня есть действие контроллера editCreateFirstFormPart
который обрабатывает некоторые поля Workflow
объект и визуализирует соответствующую первую часть двухраздельной формы.
Если я вызову маршрут этого метода действия с идентификатором хранимого объекта, форма загрузит все поля так, как должно. Я сохраняю объект базы данных, которая заполняет форму, в текущем сеансе на случай, если пользователь решит отменить редактирование во второй форме:
// Persist all changes of made in the first form part
$manager->persist($workflow);
$manager->flush();
// In case the wolkflow already exists store it in the session
if(!$newWorkflow) $this->get('session')->set($workflowSessionName, $workflowBeforeSubmit);
return $this->redirectToRoute('pec_test_pra_edit_workflow_second_part', array(
'project' => $project->getId(),
'workflow' => $workflow->getId(),
'newWorkflow' => $newWorkflow,
// Pass the name in the session of the stored workflow to the action method which handles the second form
'workflowSessionName' => $workflowSessionName,
));
Это работает как шарм. Теперь в случае (который я получаю) пользователь отправляет вторую форму через cancel
Кнопка Я хочу сбросить объект, хранящийся в базе данных, в состояние ДО того, как будет отправлена первая часть формы. Поэтому я выбираю объект, сохраненный в сеансе, и хочу persist
Это:
if($sessionObject instanceof Workflow) {
$manager = $this->getObjectManager();
$sessionObject = $session->get($workflowSessionName);
$manager->persist($sessionObject);
$manager->flush();
}
И тут я получаю следующую ошибку:
Примечание: неопределенный индекс: 0000000061675b3d0000000022ddb0a6 в вендоре \ doctrine \ orm \ lib \ Doctrine \ ORM \ UnitOfWork.php (строка 2917)
Строка 2917:return $this->entityIdentifiers[spl_object_hash($entity)];
UnitOfWork-> getEntityIdentifier (объект(Fuel)) // вызывается после prepareUpdateData
BasicEntityPersister-> prepareUpdateData (объект(MProject))
Моя сущность Workflow
имеет однонаправленный ManyToOne отношение к Project
учебный класс. MProject
класс расширяется Project
и имеет один fuel
свойство класса Fuel
,
Так один Fuel
имеет много MProject
s (один ко многим) а также Много MProject
есть один Fuel
(ManyToOne). Вот соответствующие части .orm.yml
файлы:
Fuel.orm.yml
:
'ABundle\Entity\Fuel':
...
oneToMany:
projects:
targetEntity: 'ABundle\Entity\MProject'
mappedBy: fuel
внутри Fuel
учебный класс:
class Fuel {
/**
* The collection of projects using the fuel.
*
* @var \Doctrine\Common\Collections\Collection
*/
private $projects;
...
}
MProject.orm.yml
:
'ABundle\Entity\MProject':
repositoryClass: 'ABundle\Repository\MProjectRepository'
type: entity
manyToOne:
fuel:
targetEntity: 'ABundle\Entity\Fuel'
inversedBy: projects
внутри MProject
учебный класс:
use BBundle\Entity\Project as BaseProject; // Origin of Project in my Entity
class MProject extends BaseProject implements SearchableTypeAlias {
/**
* The fuel used by the project.
*
* @var Fuel
*/
protected $fuel;
...
}
Workflow.orm.yml
:
MyBundle\Entity\Workflow:
...
manyToOne:
project:
targetEntity: BBundle\Entity\Project
cascade: [persist]
...
внутри Workflow
учебный класс:
use BBundle\Entity\Project;
class Workflow {
/**
* @var Project
*/
private $project;
...
}
Я действительно не знаю, что не так в моем случае использования, особенно потому, что нет проблем с хранением $workflow
объект с вызовом persist
в первом методе действия контроллера.
Ваша проблема в том, что вы пытаетесь сохранить сущности отдельный от EntityManager
, Workflow
, Project
объекты помечены как NEW
и получить расписание для вставки вместо обновления. Во время исследования project->fuel
ассоциация сессий Project
другой Fuel
сущность с непустым id
значение найти. Но это отстранено и id
не может быть найден в EntityManager
поэтому исключение повышается.
Объекты, которые должны иметь соответствующую строку в БД, но загружены не EntityManager
(несериализовано из сессии в вашем примере) должно быть слиты в EntityManager
, Вы должны объединить все Workflow
, Project
, Fuel
экземпляров. Самый простой способ будет настроить workflow->project
а также project->fuel
ассоциации для каскадного слияния cascade: [merge]
и слить только сессию Workflow
,
$manager = $this->getObjectManager();
$sessionObject = $session->get($workflowSessionName);
$manager->merge($sessionObject);
$manager->flush();
Обратите внимание, что это автоматически заменит значения полей сущностей на значения, извлеченные из сеанса.
Поскольку вы используете перенаправление для маршрутизации, создается новый запрос для загрузки второй части формы. На этом этапе identityMap был перестроен и не имеет ссылки на отображение (длинный идентификатор) для ранее загруженного объекта сеанса (рабочий процесс). Попробуйте снова извлечь объект из базы данных и установить свойства со значениями объекта сеанса.
PS: может быть более чистый способ сделать это, о котором я не знаю.