У меня есть объект, который является экземпляром класса сущности Workflow
, Этот рабочий процесс имеет свойство $states
который является экземпляром класса сущностей доктрин ArrayCollection
,
Часть моей Workflow
учебный класс:
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
class Workflow {
/**
* @var integer
*/
private $id;
/**
* @var Collection
*/
private $states;
/**
* Workflow constructor.
* @param ...t
*/
public function __construct(...) {
$this->states = new ArrayCollection();
...
}
/**
* Get states
*
* @return Collection
*/
public function getStates() {
return $this->states;
}
public function addState(State $state) {
$state->setWorkflow($this);
$this->states->add($state);
return $this;
}
...
}
Workflow
с и States
s отображаются и хранятся в базе данных. Здесь части являются .orm.yml
файлы сопоставления:
Workflow.orm.yml
:
MyBundle\Entity\Workflow:
type: entity
id:
id:
type: integer
generator: {strategy: AUTO}
oneToMany:
states:
targetEntity: MyBundle\Entity\State
mappedBy: workflow
cascade: [persist, remove]
orphanRemoval: true
...
State.orm.yml
:
MyBundle\Entity\State:
type: entity
id:
id:
type: integer
generator: {strategy: AUTO}
manyToOne:
workflow:
targetEntity: MyBundle\Entity\Workflow
inversedBy: states
cascade: [persist]
...
В знаю, что у меня есть Workflow
названный тестовое задание хранится с State
названный релиз. У меня есть маршрут с параметрами объекта, используя Symfonys ParamConverter с типом намека.
Вот часть routing.yml
:
my_route:
path: /project/{project}/editWorkflow/{workflow}
defaults: { _controller: "MyBundle:Test:createEditWorkflowFirstPart", workflow: 0 }
Теперь я называю маршрут с существующим проект и существующий рабочий процесс например http://localhost/app_dev.php/de/testpra/project/79/editWorkflow/first/19
и ожидаем, что Symfony загрузит workflow
в моем методе действий.
loaded
рабочий процесс как глубокий клон в моем сеансе и перезагрузите его во втором методе действия части формы, когда пользователь отправляет соответствующую кнопку WorkflowStatesType::NEXT_FORM_PART
,При звонке createEditWorkflowFirstPartAction
по маршруту метод действительно содержит $workflow
объект, который является экземпляром Workflow
но когда я сбрасываю все состояния через dump($workflow->getStates()
нет элементов в ArrayCollection
но при запуске состояний в цикле foreach ($workflow->getStates() as $state) dump($state);
Symfony создает дамп состояния рабочего процесса, хранящегося в базе данных.
У меня никогда не было такого странного поведения Symfony, поэтому я действительно не знаю, dump
это не свалка правильно или если ArrayCollection
просто загружает состояния, когда считает, что они необходимы.
Когда сейчас звоню unserialize(serialize($workflow));
в глубокий клон $workflow
десериализуется объект не выдает никакого состояния при циклическом прохождении состояний в foreach
,
Здесь createEditWorkflowFirstPartAction
метод:
public function createEditWorkflowFirstPartAction(Request $request, Project $project, Workflow $workflow = null) {
$newWorkflow = false;
if(!$workflow) {
$workflow = new Workflow($project);
$newWorkflow = true;
}
$workflowBeforeSubmit = unserialize(serialize($workflow));
dump($workflow->getStates()); // Line 106 - Contains no elements
dump($workflowBeforeSubmit->getStates()); // Line 107 - Contains no elements
foreach ($workflow->getStates() as $state) dump($state); // Line 108 - Will print out my stored State
foreach ($workflowBeforeSubmit->getStates() as $state) dump($state); // No states
$firstFormPart = $this->createForm(WorkflowStatesType::class, $workflow);
$firstFormPart->submit($request->get($firstFormPart->getName()), false);
if($firstFormPart->isSubmitted() && $firstFormPart->isValid()) {
...
}
die();
return $this->render('@MyBundle/Workflow/workflow_edit_create_first_part.html.twig', array(
'form' => $firstFormPart->createView(),
));
}
И вот соответствующий вывод (PraWorkflow
знак равно Workflow
, PraTestController
знак равно TestController
):
ArrayCollection
пусто и не держит State
(здесь id 26)?ArrayCollection
получить доступ к базе данных?unserialize(serialize(...))
работать на глубокий клон объект со всеми дочерними объектами? Если нет, то как мне это сделать, не имея ссылки на один из объектов, часть $workflow
объект?Каждое отношение (тогда как OnetoOne) загружается лениво, поэтому доктрина не заполняет ваше отношение.
Если вы хотите, добавьте пользовательский запрос в репозиторий и addSelect (alias.releationField) с соединяемой частью, и ваша коллекция будет не пустой.
Вы также можете изменить режим выборки в сущности по умолчанию на FETCH_EAGER
Вот моя реализация глубокого клонирования с коллекциями:
/**
* @ORM\Entity
* @ORM\Table(name="clients")
*/
class Client
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
* @ORM\Column(type="integer")
*/
protected $id;
// ...
/**
* @ORM\OneToMany(targetEntity="Address", mappedBy="client", cascade={"persist", "remove", "merge"}, orphanRemoval=true), fetch="EXTRA_LAZY")
* @ORM\OrderBy("title"="ASC"})
*/
protected $addresses;
// ...
public function __construct()
{
$this->addresses = new ArrayCollection();
}
// ...
public function __clone()
{
if ($this->id)
{
$this->setId(null);
}
// cloning addresses
$addressesClone = new ArrayCollection();
foreach ($this->addresses as $address)
{
/* @var Address $address */
$addressClone = clone $address;
$addressClone->setClient($this);
$addressesClone->add($addressClone);
}
$this->addresses = $addressesClone;
}
// ...
}
В контроллере просто позвони $copy = clone $client;
чтобы получить идеальную копию вашей сущности с коллекцией.