问题
It's the first time I run into this problem. I want to create a doctrine object and pass it along without having to flush it.
Right after it's creation, I can display some value in the object, but I can't access nested object:
$em->persist($filter);
print_r($filter->getDescription() . "\n");
print_r(count($filter->getAssetClasses()));
die;
I get:
filter description -- 0
(I should have 19 assetClass)
If I flush $filter, i still have the same issue (why oh why !) The solution is to refresh it:
$em->persist($filter);
$em->flush();
$em->refresh($filter);
print_r($filter->getDescription() . " -- ");
print_r(count($filter->getAssetClasses()));
die;
I get:
filter description -- 19
unfortunately, you can't refresh without flushing.
On my entities, I've got the following:
in class Filter:
public function __construct()
{
$this->filterAssetClasses = new ArrayCollection();
$this->assetClasses = new ArrayCollection();
}
/**
* @var Collection
*
* @ORM\OneToMany(targetEntity="FilterAssetClass", mappedBy="filterAssetClasses", cascade={"persist"})
*/
private $filterAssetClasses;
public function addFilterAssetClass(\App\CoreBundle\Entity\FilterAssetClass $filterAssetClass)
{
$this->filterAssetClasses[] = $filterAssetClass;
$filterAssetClass->setFilter($this);
return $this;
}
in class FilterAssetClass:
/**
* @var Filter
*
* @ORM\ManyToOne(targetEntity="App\CoreBundle\Entity\Filter", inversedBy="filterAssetClasses")
*/
private $filter;
/**
* @var Filter
*
* @ORM\ManyToOne(targetEntity="AssetClass")
*/
private $assetClass;
public function setFilter(\App\CoreBundle\Entity\Filter $filter)
{
$this->filter = $filter;
return $this;
}
Someone else did write the code for the entities, and i'm a bit lost. I'm not a Doctrine expert, so if someone could point me in the good direction, that would be awesome.
Julien
回答1:
but I can't access nested object
Did you set those assetClasses in the first place?
When you work with objects in memory (before persist), you can add and set all nested objects, and use those while still in memory.
My guess is that you believe that you need to store objects to database in order for them to get their IDs assigned.
IMHO, that is a bad practice and often causes problems. You can use ramsey/uuid library instead, and set IDs in Entity constructor:
public function __construct() {
$this->id = Uuid::uuid4();
}
A database should be used only as a means for storing data. No business logic should be there.
I would recommend this video on Doctrine good practices, and about the above mentioned stuff.
回答2:
Your problem is not related to doctrine nor the persist/flush/refresh sequence; the problem you describe is only a symptom of bad code. As others have suggested, you should not be relying on the database to get at your data model. You should be able to get what you are after entirely without using the database; the database only stores the data when you are done with it.
Your Filter class should include some code that manages this:
// Filter
public function __contsruct()
{
$this->filterAssetClasses = new ArrayCollection();
}
/**
* @ORM\OneToMany(targetEntity="FilterAssetClass", mappedBy="filterAssetClasses", cascade={"persist"})
*/
private $filterAssetClasses;
public function addFilterAssetClass(FilterAssetClass $class)
{
// assuming you don't want duplicates...
if ($this->filterAssetClasses->contains($class) {
return;
}
$this->filterAssetClasses[] = $class;
// you also need to set the owning side of this relationship
// for later persistence in the db
// Of course you'll need to create the referenced function in your
// FilterAssetClass entity
$class->addFilter($this);
}
You may have all of this already, but you didn't show enough of your code to know. Note that you should probably not have a function setFilterAssetClass() in your Filter entity.
来源:https://stackoverflow.com/questions/43210485/symfony-doctrine-cannot-use-object-without-refreshing