I have two entities with a oneToMany relationship:
Post entity:
...
oneToMany:
images:
mappedBy: post
targetEntity: Shop\Bundle\ManagementBundle\Entity\Image
Image entity:
...
manyToOne:
post:
targetEntity: Shop\Bundle\ManagementBundle\Entity\Post
inversedBy: images
joinColumn:
onDelete: cascade
With $entity
instance of Post
, when I was doing $entity->getImages()
, I was receiving something like:
object(Doctrine\ORM\PersistentCollection)[65]
private 'snapshot' =>
array (size=0)
empty
private 'owner' =>
object(Acme\Bundle\ImageUpBundle\Entity\Post)[54]
private 'id' => int 41
private 'title' => string 'kbd' (length=3)
private 'images' =>
&object(Doctrine\ORM\PersistentCollection)[65]
private 'association' =>
array (size=15)
'fieldName' => string 'images' (length=6)
'targetEntity' => string 'Shop\Bundle\ManagementBundle\Entity\Image' (length=38)
'mappedBy' => string 'post' (length=4)
'type' => int 4
'inversedBy' => null
'isOwningSide' => boolean false
'sourceEntity' => string 'Shop\Bundle\ManagementBundle\Entity\Post' (length=37)
'fetch' => int 2
'cascade' =>
array (size=0)
empty
'isCascadeRemove' => boolean false
'isCascadePersist' => boolean false
'isCascadeRefresh' => boolean false
'isCascadeMerge' => boolean false
'isCascadeDetach' => boolean false
'orphanRemoval' => boolean false
private 'em' =>
....
But now i unfortunately get null
.
I really did all my best to figure out what might cause such issue. Your help is much appreciated.
Edit:
given an in integer $id, I fetch a Post entity using:
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ShopManagementBundle:Post')->find($id);
I successfully get all the attributes of Post entity except from images
.
Well here are the things that solved my issue:
1- I gathered all One To Many associations under one oneToMany
parameter in config file. In other words, instead of having:
oneToMany:
images:
targetEntity....
....
oneToMany:
messages:
targerEntity...
....
I would have:
oneToMany:
images:
targerEntity...
....
messages:
targerEntity...
....
- I generated entities again using
app/console doc:gen:entities
making the only one constructor constructs the two ArrayCollection
s.
/**
* Constructor
*/
public function __construct()
{
$this->messages = new \Doctrine\Common\Collections\ArrayCollection();
$this->images = new \Doctrine\Common\Collections\ArrayCollection();
}
Now when I call $em->getRepository('ShopManagementBundle:Post)->find($id)
I have the child entities (Images
) attached to my parent entity (Post
) when concrete records exist in database, and not Null. When I insantiate a new entity using new Post()
, I have empty ArrayCollection and not Null.
I know this answer is lacking of programming logic and seems arbitrary effort, but I write it in the sake of sharing in the case someone encounters suddenly this problem (As I did). I hope it helps.
$entity = $em->getRepository('ShopManagementBundle:Post')->find($id);
By Default, you will get only the proxy object of the child entities, this lazy way of fetching the associated entities is called Lazy loading, which will fetch values from images entity only a call to its getter method is invoked such as
$entity->getImage();
To load all the associated entities at one shot, you should instruct doctrine to do eager loading. This can be done using DQL, unfortunately its not possible to instruct using find method
$query = $em->createQuery("SELECT p FROM Shop\Bundle\ManagementBundle\Entity\Post p");
$query->setFetchMode("Shop\Bundle\ManagementBundle\Entity\Post", "images", \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER);
$query->execute();
Make sure your column name, member name and method naming all syntactically align. For example 'searchCampaignType':
ORM Column: searchCampaignTypeId
Member: $searchCampaignType
Getter: getSearchCampaignTypes
Setter: setSearchCampaignTypes
Other steps to take:
- Regenerate your Doctrine Proxies
- If you are using memcached then ensure you restart it or
rebuild the data
The question was oneToMany. The example below is ManyToMany but the principle is the same.
/**
* @ORM\ManyToMany(targetEntity="CampaignType")
* @ORM\JoinTable(name="Roles__SearchCampaignTypes",
* joinColumns={@ORM\JoinColumn(name="roleId", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="searchCampaignTypeId", referencedColumnName="id")}
* )
**/
private $searchCampaignTypes;
/**
* @return ArrayCollection
*/
public function getSearchCampaignTypes()
{
return $this->searchCampaignTypes;
}
/**
* @param $searchCampaignTypes
*/
public function setSearchCampaignTypes($searchCampaignTypes)
{
$this->searchCampaignTypes = $searchCampaignTypes;
}