XF 2.0 Caching finder results

Rasmus Vind

Well-known member
I wrote a neat little function that allows you to fetch from a finder, but only if it is not cached.
PHP:
class Util
{
    public static function cachedFinderFetch(\XF\Mvc\Entity\Finder $finder, $cacheKey, $lifeTime = 0)
    {
        $app = \XF::app();
        $em = $app->em();
        $cache = $app->cache();
        if (!$cache || !$cache->contains($cacheKey)) {
            $hydrationMap = $finder->getHydrationMap();
            $results = $app->db()->query($finder->getQuery());
            $rawItems = [];
            while ($row = $results->fetchAliasGrouped()) {
                $rawItems[] = $row;
            }
            if ($cache) {
                $cacheData = ['items' => $rawItems, 'hydrationMap' => $hydrationMap];
                $cache->save($cacheKey, $cacheData, $lifeTime);
            }
        } else {
            $cacheData = $cache->fetch($cacheKey);
            $rawItems = $cacheData['items'];
            $hydrationMap = $cacheData['hydrationMap'];
        }
        $items = array_map(function (array $item) use ($em, $hydrationMap) {
            return $em->hydrateFromGrouped($item, $hydrationMap);
        }, $rawItems);
        return $em->getBasicCollection($items);
    }
}

It could be rewritten to extend the \XF\Mvc\Entity\Finder but this is the one I use.

I use it to cache results for widgets:
PHP:
$widgetKey = $this->widgetConfig->widgetKey;
$cacheKey = "widget_cache_{$widgetKey}";
$finder = $this->finder('VindIT\Repository:Bundle')
    ->with(['PrimaryImage', 'PrimaryImage.ImageData'])
    ->where('Thread.node_id', $this->options['node_id'])
    ->where('Thread.discussion_state', 'visible')
    ->where('Thread.discussion_type', '')
    ->where('review_state', ['pending', 'approved', 'awaiting_update'])
    ->order('post_date', 'DESC')
    ->limit($bundlesPerPanel * $panelCount);
$bundles = \VindIT\Repository\Util::cachedFinderFetch($finder, $cacheKey, 600);

I feel like this could be integrated into XenForo with a Finder::fetchCached($lifeTime) method or something to simplify the caching workflow.

@Kier, @Mike, what do you think?
 
Top Bottom