I have an object which is an instance of the entity class Workflow. This workflow has a property $states which is an instance of doctrines entity class ArrayCollection.
Part of my Workflow class:
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;
}
...
}
Workflows and Statess are mapped and get stored into the database. Here parts are the .orm.yml mapping files:
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]
...
In know that I have a Workflow named test stored with a State named release. I have a route with object parameters using Symfonys ParamConverter with type hinting.
Here is a part of the routing.yml:
my_route:
path: /project/{project}/editWorkflow/{workflow}
defaults: { _controller: "MyBundle:Test:createEditWorkflowFirstPart", workflow: 0 }
Now I call the route with an existing project and an existing workflow e.g. http://localhost/app_dev.php/de/testpra/project/79/editWorkflow/first/19 and expect Symfony to load the workflow in my action method.
My goal is to store the loaded workflow as a deep clone in my session and reload it in a second form part action method when the user submits an according button WorkflowStatesType::NEXT_FORM_PART.
Now the problem
When calling the createEditWorkflowFirstPartAction via route the method indeed holds a $workflow object which is an instance of Workflow but when I dump all states via dump($workflow->getStates() there are no elements in the ArrayCollection but when running the states in a loop foreach ($workflow->getStates() as $state) dump($state); Symfony dumps the State of the Workflow stored in the database.
I never had such a strange behaviour of Symfony so I really don´t know if its the dump that does not dump right or if the ArrayCollection just loads the states when it thinks they are needed.
When now calling unserialize(serialize($workflow)); to deep clone the $workflow the unserialized object does not dump any state when looping through states in a foreach.
Here is the createEditWorkflowFirstPartAction method:
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(),
));
}
And here is the according output (PraWorkflow = Workflow, PraTestController = TestController):
- Why are the
ArrayCollections empty and doesn´t hold theState(here id 26)? - Why do I get the State when using a foreach loop? Does
ArrayCollectionaccess the database? - Does
unserialize(serialize(...))work to deep clone an object with all child objects? If not, how should I do it without having any reference to one of the objects part of the$workflowobject?
