Search code examples
laravelcachingeloquentcasting

Cache eloquent model with all of it's relations then convert it back to model with relations?


I am trying to optimize a project that is working pretty slow using caching. I'm facing a problem that I don't quite understand how to cache full eloquent models with their relationships and later on covert them back to a model with all relations intact. Here's a fragment of my code

if (Cache::has($website->id.'_main_page')) {
        $properties = (array) json_decode(Cache::get($website->id.'_main_page'));
        $page = Page::hydrate($properties);
      }else{
        $expiresAt = now()->addMinutes(60);
        $page = Page::with(['sections', 'pageSections.sectionObjects'])->where('website_id', $website->id)->where('main', 1)->first();
        Cache::put($website->id.'_main_page', $page->toJson(), $expiresAt);
      }

Problem is, hydrate seems to be casting this data as a collection when in fact it's suppose to be a single model. And thus later on I am unable to access any of it's properties without getting errors that they don't exists. $properties variable looks perfect and I would use that but I need laravel to understand it as a Page model instead of stdClass, I also need all of the relationships to be cast into their appropriate models. Is this even possible? Any help is much appreciated


Solution

  • Is there any reason you can't use the cache like this

    $page = Cache::remember($website->id.'_main_page', 60 * 60, function () use ($website) {
        return Page::with(['sections', 'pageSections.sectionObjects'])
             ->where('website_id', $website->id)
             ->where('main', 1)
             ->first();
    });
    

    Conditional

    $query = Page::query();
    $key = $website->id.'_main_page';
    
    if (true) {
        $query = $query->where('condition', true);
        $key = $key . '_condition_true';
    }
    
    $query::with(['sections', 'pageSections.sectionObjects'])
             ->where('main', 1)
    
    $page = Cache::remember($key, 60 * 60, function () use ($query) {
        return $query->first();
    });