Gerardo
Gerardo

Reputation: 5830

Symfony Cache Component and Lazy Loading

I am using the Cache Component for Symfony 3.2. I have an entity named MenuItem that has a many to one relationship with other:

class MenuItem 
{
  //...

  /**
   * @ORM\ManyToOne(targetEntity="BaseBundle\Entity\ProductCategory")
   * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
   */
  private $category;

  //...

In a service, I want to retrieve all the menuitems and save them in the cache:

    $menuItemsCached = $this->cache->getItem('app.menu_items');
    if ($menuItemsCached->isHit()) {
        $menuItems = $menuItemsCached->get();
    } else {
        $repository = $this->em->getRepository('WebBundle:MenuItem');
        $menuItems = $repository->findBy([], ['weight' => 'ASC']);
        $menuItemsCached->set($menuItems);
        $this->cache->save($menuItemsCached);
    }
    return $menuItems;

The problem is that, when I get the array from the cache, the entities ProductCategory inside my MenuItems are proxies as you can see:

  5 => MenuItem {#3428 ▼
    #id: 3
    #name: "Vinils"
    #weight: 60
    #selector: "vinil"
    -categoryCollection: ProductCategory {#3429 ▼
      +__isInitialized__: false
      #id: 23
      #name: ""

And if I called getName() it returns "" instead the Product Category name (lazy loading not working).

I don't understand this behaviour, so I would be very pleasant if anyone can explain me because lazy loading is not working (I suppose I can configure the relationship with fetch="EAGER" to avoid this issue).

Thanks.

Upvotes: 1

Views: 638

Answers (1)

yceruto
yceruto

Reputation: 9585

It's a common side effect of "entity not managed", this happen because your cached entities are out of scope from entity manager just after retrieves all menu items from cache ($menuItems = $menuItemsCached->get()) hence the related proxies are "dead".

All you need is merge each cached entity to the current entity manager and the proxies will "live" again:

$menuItems = $menuItemsCached->get();
foreach ($menuItems as &$menuItem) {
    $menuItem = $entityManager->merge($menuItem);
}

Later, you would be able to get the name of each product category in a lazy way.

Upvotes: 2

Related Questions