symfony 2 doctrine query builder Apc cache not saving collection objects

507 Views Asked by At

I have a repository function that retrieves random products depending on category. I am using APC cache to cache the results and random products only when cache expired. Everything works good except the images for the product are not saved in cache. The Product Entity has a OneToMany relation to ProductImages Entity like this:

/**
 * @var arrayCollection
 *
 * @ORM\OneToMany(targetEntity="ProductImage", mappedBy="product", cascade={"persist", "remove"}, orphanRemoval=true)
 */
private $images;

public function __construct()
{
    $this->images = new ArrayCollection();
}

/**
 * @var Product
 *
 * @ORM\ManyToOne(targetEntity="Product", inversedBy="images")
 * @ORM\JoinColumn(name="product_id", referencedColumnName="id")
 */
private $product;

My repository function:

/**
 * @param $category
 * @param $limit
 * @param $source
 * @param $cacheExpiresTime
 * @return \Doctrine\ORM\Query
 */
public function findByCategoryLimit($category, $limit, $source, $cacheExpiresTime = 3600)
{
    $cacheDriver = new ApcCache();
    $cacheId = 'category_'.$category->getId().'_products';
    $config = $this->getEntityManager()->getConfiguration();
    $config->setResultCacheImpl($cacheDriver);
    if ($config->getResultCacheImpl()->contains($cacheId))
    {
        return $config->getResultCacheImpl()->fetch($cacheId);
    }
    $qb = $this->createQueryBuilder('p');
    $qb->select('p')
        ->leftJoin('p.sourceCategory', 's')
        ->where('s.category = :category')
        ->setMaxResults($limit)
        ->setParameter('category', $category);
    if (!empty($source)){
        $qb->andWhere('p.source = :source');
        $qb->setParameter('source', $source);
    }
    $qb->orderBy('p.title', 'ASC');
    if($this->getCategoryTotalProducts($category) > $limit) {
        $qb->setFirstResult(rand(1, ($this->getCategoryTotalProducts($category) - $limit)));
    }
    $query = $qb->getQuery();
    //$query->setResultCacheDriver($cacheDriver);
    //$query->useResultCache(true, $cacheExpiresTime, $cacheId);
    $result = $query->getResult();
    $config->getResultCacheImpl()->save($cacheId, $result, $cacheExpiresTime);

    return $result;

}

When the product is loaded from db the images appear just fine but when is loaded from cache the images are gone (empty). What i am doing wrong here? I tried different approaches and searched for a solution with no success. The $cacheExpiresTime is set to 20

Thanks in advance.

2

There are 2 best solutions below

0
On

The problem was the query offset. Here is the solution. Now it works as expected.

/**
 * @param $category
 * @param $limit
 * @param $source
 * @param $cacheExpiresTime
 * @return \Doctrine\ORM\Query
 */
public function findByCategoryLimit($category, $limit, $source, $cacheExpiresTime = 3600)
{
    $cacheDriver = new ApcCache();
    $cacheId = 'category_'.$category->getId().'_products';
    $config = $this->getEntityManager()->getConfiguration();
    $config->setResultCacheImpl($cacheDriver);
    $offset = 0;
    if($this->getCategoryTotalProducts($category) > $limit) {
        $offset = rand(1, ($this->getCategoryTotalProducts($category) - $limit));
    }

    if ($config->getResultCacheImpl()->contains($cacheId))
    {
        $offset = $config->getResultCacheImpl()->fetch($cacheId);
    }

    $qb = $this->createQueryBuilder('p');
    $qb->select('p')
        ->leftJoin('p.sourceCategory', 's')
        ->where('s.category = :category')
        ->setMaxResults($limit)
        ->setParameter('category', $category);
    if (!empty($source)){
        $qb->andWhere('p.source = :source');
        $qb->setParameter('source', $source);
    }
    $qb->orderBy('p.title', 'ASC');
    $qb->setFirstResult($offset);

    $query = $qb->getQuery();
    $query->useQueryCache(true);
    $query->useResultCache(true);
    $result = $query->getResult();
    if (!$config->getResultCacheImpl()->contains($cacheId)) {
        $config->getResultCacheImpl()->save($cacheId, $offset, $cacheExpiresTime);
    }

    return $result;

}
1
On

Did you try to eager load images? (Append join and select to query). It's a workaround I know:)