Get child entities returns null instead of arrayCo

2019-04-02 16:34发布

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.

3条回答
Fickle 薄情
2楼-- · 2019-04-02 16:43

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...
      ....
  1. I generated entities again using app/console doc:gen:entities making the only one constructor constructs the two ArrayCollections.
/**
     * 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.

查看更多
闹够了就滚
3楼-- · 2019-04-02 17:02
$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();
查看更多
倾城 Initia
4楼-- · 2019-04-02 17:04

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;
}
查看更多
登录 后发表回答