Laravel cache::remember is returing object as an array

北城余情 提交于 2020-01-07 04:20:26

问题


Laravel Cache::remember is returning a LengthAwarePaginator object as an array.

function getNotifications( $userID ) {
    $values = Cache::remember('cache-key', 10, function() {

        $query = DB::table( 'user_notifications' )
                ->leftJoin( 'notifications', 'user_notifications.notification_id', '=', 'notifications.id' )
                ->where( 'user_notifications.user_id', $userID )
                ->select( 'notifications.*' )
                ->orderBy('created_at', 'DESC')
                ->paginate(5);

        return $query;

    });

    return $values;
}

If I dd($query) before returning from Cache closure, it's returning the following object, that accepts $value->links() to display pagination.

But whenever the Cache is storing $query into $values it's returning values as an array:

I tried commenting out the unserialize-block:

/*foreach( $values as $key => $value ) :
    $values[$key]->meta = self::maybeUnserialize($value->meta);
endforeach;*/

and confirmed that, that's not the cause.

I also tried, but failed:

$values = collect($values);

With multiple check and cross-check I am confirming that, the issue is the Cache::remember.

How can I force the Cache::remember return things as it is? So that I can let $object->links() work for me.

The actual code can be found here.


回答1:


Issue is, Cache is made to store data, not the instance. So there are two ways to do this:

  1. When caching, cache information per page, or
  2. Get all the data while fetching, but make your own pagination

Solution 1:

We went for the second. But in case you need to go for the first solution, here's the code, I got from Laracasts, provided by chrisml:

$statuses = Cache::remember('statuses_' . $id . '_page_' . $page, 3, function() use ($event, $sort) {
    return $event->statuses()
        ->with('comments')
        ->latest()
        ->paginate(10);
});

On the above code, the cache key is changing on every page, so the cache is storing per page.

Solution 2:

But for my case, we thought we should go for the second, and that would be wise for us, in our case. So, we've to make our own pagination. My luck that, psampaz did the base for us on their blog:

  • Custom data pagination with Laravel 5 — by psampaz

So, instead of using ->paginate() we're fetching all the data first, and caching them as previous.

$values = Cache::remember('cache-key', 10, function() {

    $query = DB::table( 'user_notifications' )
            ->leftJoin( 'notifications', 'user_notifications.notification_id', '=', 'notifications.id' )
            ->where( 'user_notifications.user_id', $userID )
            ->select( 'notifications.*' )
            ->orderBy('created_at', 'DESC')
            ->get(); // <----------- here

    return $query;

});

But before returning the $values, we're making our own pagination. We made some fixes to psampaz's code:

use Illuminate\Support\Collection;
use Illuminate\Pagination\LengthAwarePaginator;

function getNotifications( $userID ) {

    // Collapsed the cached values here :)
    $values = Cache::remember('cache-key', 10, function() {...});

    // Get current page form url e.g. &page=6.
    $currentPage = LengthAwarePaginator::resolveCurrentPage();

    // Get current path.
    $currentPath = LengthAwarePaginator::resolveCurrentPath();

    // Create a new Laravel collection from the array data.
    $collection = new Collection($values);

    // Define how many items we want to be visible in each page.
    $perPage = 5;

    // Slice the collection to get the items to display in current page.
    $results = $collection->slice(($currentPage - 1) * $perPage, $perPage)->all();

    // Create our paginator and pass it to the view.
    $values = new LengthAwarePaginator($results, count($collection), $perPage, $currentPage, ['path' => $currentPath]);

    return $values;
}

And finally we can easily use the $object->links() for pagination, and it's awesome! :)



来源:https://stackoverflow.com/questions/44028121/laravel-cacheremember-is-returing-object-as-an-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!