【问题标题】:How to utilize Laravel Cache in API?如何在 API 中使用 Laravel 缓存?
【发布时间】:2020-09-04 21:17:48
【问题描述】:

在我的公司,我们有三个用户角色:管理员、医生和客户。他们都可以查看其中一个记录表,其中我们有大约 100 万行,我们需要缓存数据库中的结果。

我已经阅读了 10 篇关于 Stack 和其他内容的帖子,但我仍在尝试找出正确的缓存方式。

我读到的是正确的方法是缓存每页,所以我根据用户页面选择缓存第 1 页、第 2 页等。这一切都很好。

但是每个用户角色看到不同的数据集,他们选择了不同的过滤器,这就是问题开始的地方。我缓存结果,然后过滤分页的 10 行似乎有点多余。

我不知道是否应该使用所选参数缓存每个用户角色的结果?

或者我应该先缓存所有结果,然后加载所需的关系并使用来自用户的参数过滤集合,然后创建分页?

或者我不应该在这个例子中使用缓存而只使用简单的分页?

// Set the cache time
            $time_in_minutes = 5 * 60;

            // Request page and if not set then default page is 1
            $page = $paginationObject['page'];

            // Set items per page
            $per_page = $paginationObject['perpage'] ? $paginationObject['perpage'] : 10;

            // Set the cache key based on country
            $cache_key = "l04ax_pct_dispensing_forms_{$request->get('country')}_page_{$page}_per_page_$per_page";
            // Cache::forget($cache_key);
            // Set base query for results
            $baseQuery = $this->model->with(['details', 'patient']);

            // Assign appropriate relations based on user role
            if (Auth::user()->isPhysician()) {
                $baseQuery->physicianData();
            }
            else if (Auth::user()->isManufacturer()) {
                $baseQuery->manufacturerData();
            }
            else if (Auth::user()->isSuperAdmin() || Auth::user()->isAdmin()) {
                $baseQuery->adminData();
            }

            //--------------------------------------
            // Add filtering params from request
            // -------------------------------------
            $baseQuery->when($request->has('atc_code'), function ($query) use ($request) {
                if ($request->get('atc_code') === NULL) {
                    throw new RequestParameterEmpty('atc_code');
                }
                $query->whereHas('details', function ($subQuery) use ($request) {
                    $subQuery->where('atc_code', $request['atc_code']);
                });
            })
                ->when($request->has('id'), function ($query) use ($request) {
                    if ($request->get('id') === NULL) {
                        throw new RequestParameterEmpty('id');
                    }
                    $query->where('l04ax_dispensing_forms.id', $request['id']);
                })
                ->when($request->has('pct_patients_hematology_id'), function ($query) use ($request) {
                    if ($request->get('patient_id') === NULL) {
                        throw new RequestParameterEmpty('patient_id');
                    }
                    $query->where('patient_id', $request['patient_id']);
                })
                ->when($request->has('physician_id'), function ($query) use ($request) {
                    if ($request->get('physician_id') === NULL) {
                        throw new RequestParameterEmpty('physician_id');
                    }
                    $query->where('physician_id', $request['physician_id']);
                })
                ->when($request->has('date'), function ($query) use ($request) {
                    if ($request->get('date') === NULL) {
                        throw new RequestParameterEmpty('date');
                    }
                    $query->whereDate('created_at', Carbon::parse($request->get('date'))->toDateString());
                })
                ->when($request->has('deleted'), function ($query) use ($request) {
                    if ($request->get('only_deleted') === NULL) {
                        throw new RequestParameterEmpty('only_deleted');
                    }
                    $query->onlyTrashed();
                })
                ->when($request->has('withTrashed'), function ($query) use ($request) {
                    if ($request->get('withTrashed') === NULL) {
                        throw new RequestParameterEmpty('withTrashed');
                    }
                    $query->withTrashed();
                });

            // Remember results per page into cache
            return Cache::remember($cache_key, $time_in_minutes, function () use ($baseQuery, $per_page, $page) {
                return new L0axPctDispensingFormsCollection($baseQuery->paginate($per_page, ['*'], 'page', $page));
            });

在这个例子中,结果是按页面缓存的,但是当不同的用户登录时,结果是错误的。

解决这个问题的最佳方法是什么?

【问题讨论】:

    标签: laravel laravel-7


    【解决方案1】:

    我不建议缓存这个,因为你已经遇到了这个问题。缓存在某些领域非常有用(例如,对于参考数据,如国家或货币的持久列表),但对于特定于用户的数据,我会避免。

    如果你真的想要缓存,你可以使用cache tagging(redis 仅支持使用phpredis driver)来按用户 ID 进行标记。但是,如前所述,我不建议在这种情况下使用!

    如果您的缓存需求是由页面加载缓慢的情况驱动的,我建议您安装 Laravel Debugbar,并检查您的 api 调用生成了多少查询。

    如果您发现单个 api 调用生成的查询比您正在加载的记录数多,那么您可能遇到了“n + 1 问题”并且需要 eager load 任何嵌套关系而不是在您的资源。

    P.s 只需调用一次Auth::user(),您就可以立即减少此控制器方法生成的查询数量。例如$user = Auth::user() 然后$user->isSuperAdmin();

    【讨论】:

      猜你喜欢
      • 2020-01-18
      • 2012-12-25
      • 2013-01-26
      • 2017-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-18
      • 2020-01-22
      相关资源
      最近更新 更多