如何用laravel Cache优化索引方法?

时间:2016-05-05 07:57:29

标签: laravel caching

是否可以重构此方法? 从数据库缓存数据的最佳做法是什么? 我应该在Controller或Repository还是其他地方进行?

public function index(Request $request)
  {
    $requestData= trim($request->only(['keyword', 'tag', 'element']));
    $requestData['type']= trim($request->input('type', 'items'));
    $requestData['address'] = trim($request->input('street'.'house'.'corpus'));

    foreach ($requestData as $key => $value) {/* why use loop?*/
      if($key == 'keyword'){/* result without cache*/
         $requestData['field'] = trim($request->input('field', 'title'));
         $data= $this->model->byKeyword($type, $field, $keyword);
         $data['items']= $this->sort($data, $requestData);
      }
      else{
         $data['items'] = Cache::remember($requestData['type'].$key, 10080, function() use ($key, $value) {
        $method = 'by' . $key;
        $data = $this->model->$method($value)->orderBy('premium', 'desc'); 
                $this->sort($data, $requestData);
          });
      }
    }

    if(!$data['items']->first()) { 
      return back()
        ->withInput()
        ->with('status', 'Could not find anything try again!');
     }
    return $this->getView('index/index',$data);
}

排序方法:

public function Sort($data,$request)
{
    $requestData = $request->only(['limitBy', 'sortBy', 'offset', 'limit']);
    $requestData['type'] = $request->input('type', 'items');

//if $requestData == 'limitBy' 

    if($requestData['type'] == 'materials' ||  $requestData['type'] == 'groups')
    {
        $data->whereHas($requestData['type'] == 'groups' ? 'users' : 'user',function($query){
            $query->whereHas('addresses',function($subquery){
                $subquery->whereId( Auth::user()->addresses()->first()->id);
            });
        });
    }else{
        $data->ByExpireDate(
            [Carbon::now(),$requestData['limiBy'] == 'today_expire' ? Carbon::tomorrow() : Carbon::now()->addWeek(1)],
            $requestData['limiBy'] == 'today_expire' ? '1440' : '10080');
    }

//if $requestData == 'limit' 
    $data->where($requestData['limit'],'1');
//if $requestData == 'sortBy' 
    $data->orderBy($requestData['sortBy'],$requestData['direction'] );
//if $requestData == 'offset' 
    $data->skip($requestData['offset'])->take($requestData['limit']);
    return $data->count() > 1 ? $data->paginate(15) : $data->get();
}

我还没有完成这两种方法,因为我不明白如何重构它。 第一种方法按照之前的说法返回数据,而另一种方法则将其分类。

我认为修复getView方法并不重要,因为它只检查现有文件并收集meta:

public function getView($path,$data = null)
    {
        logger()->info(__METHOD__);
        if ( ! preg_match('/[^a-z\-_]+/', $path)) {  return 'wrong url';}//add Exception
        if ( ! view()->exists($path)) {              return 'wrong path view';}//add Exception

        $meta  = $this->getMeta($data);
        return view($path,compact('data','meta'));
    }

提前谢谢。

1 个答案:

答案 0 :(得分:1)

  

是否可以重构此方法?

是的!请考虑以下两点:

  1. 您是否可以在6个月内快速浏览此代码并了解它的作用,或者更好的示例......另一位正在查看代码的开发人员可以通过它扫描并了解其中的内容正在进行?如果答案是否定的,那么请确保你可以重构!
  2. 如果你需要很多条件逻辑(即你的if块),那么考虑简化代码的可读性,你可以尝试将方法提取到方法中,或者如果你一遍又一遍地执行相同的检查把它扔进一个循环中。请查看以下链接:http://zaengle.com/blog/simplifying-conditional-expressions
  3. 我对您的代码的一些即时观察是:

    • 我不完全确定你要做什么
    • 为什么要抓取所有请求数据,然后执行一个巨大的if/else if阻止,其中只有一个分支将被执行(我希望您理解这一点)为什么不要'你刚刚设置一个循环?
    • if/else if区块周围的缩进很差,这使得它比现在更难理解(可能会复制并粘贴到SO中,所以如果情况如此,你可以忽略这一点)
      

    从数据库缓存数据的最佳做法是什么?

    从未真正使用Laravel中的缓存,但是考虑到有很多方法可以完成同样的工作,每个工作都有自己的优势。您最好的方法应该是衡量可用的不同选项,并选择最适合您应用的选项。在文档中查看Laravel支持的不同选项:https://laravel.com/docs/5.2/cache#configuration

      

    我应该在Controller或Repository还是其他地方进行?

    同样,从未真正使用过Laravel中的缓存,但总的来说,如果你可以将它分成自己的类并在需要时将其拉入,那么就这样做。想想这里的单一责任原则,您的控制器或存储库是否负责缓存?如果不是,则尝试将其解压缩并将其拉入控制器或任何需要的位置。

    修改

      

    谢谢!请你能提供额外的帮助并告诉我你的意思是什么,只需设置一个循环"?在上面的示例中,我尝试完成从存储库读取数据并将结果转移到缓存中。我希望你理解我的观点或我的英语。提前谢谢你。

    一步一步地完成它,希望这有帮助!

    public function index(Request $request)
    {
        logger()->info(__METHOD__);
        $keyword  = $request->input('keyword');
        $street   = $request->input('street');
        $house    = $request->input('house');
        $corpus   = $request->input('corpus');
        $tag      = $request->input('tag');
        $element  = $request->input('element');
        $field    = $request->input('field', 'title');
        $type     = $request->input('type', 'items');
    

    使用only()方法将8行合并为一行,更加清晰!

    $requestData = $request->only(['keyword', 'street', 'house', 'corpus', 'tag', 'element', 'field', 'type']);
    

    您真的需要最后两个字段的默认值吗?如果是这样,你可以这样做:

    $requestData = $request->only(['keyword', 'street', 'house', 'corpus', 'tag', 'element']); // only get first 6
    $requestData['field'] = $request->input('field', 'title');
    $requestData['type'] = $request->input('type', 'items');
    

    我不知道你在这里做什么,因为你使用调用排序方法的return语句结束方法 你在if语句中的其他分支都对缓存做了些什么,我认为你在这里做错了什么?

    if (isset($keyword)) {
        $data['items'] = $this->model->search($type, $field, $keyword)->orderBy('premium', 'desc');
        return $this->sort($data['items'], $request); // ending the method here!
    } 
    

    如果你看看其他所有的分支,你就会做同样的事情

    1. 调用缓存记住
    2. 记住回调中的
      1. 调用方法
      2. 返回排序(为什么?)
    3. 以下是每个分支的内部工作原理:

      $data['items'] = Cache::remember($type . $tag, 10080, function() use ($type, $tag, $request) {
          $data = $this->model->byTag($type, $tag)->orderBy('premium', 'desc');
          return $this->sort($data, $request);
      });
      $data['items'] = Cache::remember($type . $element, 10080, function() use ($type, $element, $request) {
          $data = $this->model->byElement($type, $element)->orderBy('premium', 'desc');
          return $this->sort($data, $request);
      });
      $data['items'] = Cache::remember($type . $street . $house . $corpus, 10080, function() use ($type, $street, $house, $corpus, $request) {
          $data = $this->model->byAddress($type, $street, $house, $corpus);
          return $this->sort($data, $request);
      });
      $data['items'] = Cache::remember($type, 10080, function() use ($type, $request) {
          $data = $this->model->byType($type)->orderBy('premium', 'desc');
          return $this->sort($data, $request);
      });
      

      所以要抽象它,你想这样看:

      $data['items'] = Cache::remember(/* keyForCache */, 10080, function() use (/* whatever we need to use */) {
          $data = $this->model->/* methodToCall */(/* request data value */)->orderBy('premium', 'desc');  // don't get what this method is doing at all! Sorry!
          return $this->sort($data, $requestData); // don't get what this method is doing at all! Sorry!
      });
      

      如果我老实说,你的代码对我来说仍然没有多大意义,所以我只是简单地让我的生活变得简单 我们假设您的请求数据如下所示:

      $requestData = [
          'keyword' => 'some value from request',
          'street'  => 'some value from request',
          'house'   => 'some value from request',
          'corpus'  => 'some value from request',
          'tag'     => 'some value from request',
          'element' => 'some value from request',
          'field'   => 'some value from request',
          'type'    => 'some value from request',
      ];
      

      您可以遍历数组,然后将缓存记忆函数应用于数组的每个项目

      foreach ($requestData as $key => $value) {
          Cache::remember($key, 10080, function() use ($key, $value) {
              $method = 'by' . $key;
              $data = $this->model->$method($value)->orderBy('premium', 'desc'); // shouldn't there be a first or get here?
              return $this->sort($data, $requestData); // don't get what this method is doing at all! Sorry!
          });
      }
      

      或者你也可以在这里使用Laravel的集合:

      $collection = collect($requestData);
      
      $collection->each(function ($value, $key) {
          Cache::remember($key, 10080, function() use ($key, $value) {
              $method = 'by' . $key;
              $data = $this->model->$method($value)->orderBy('premium', 'desc'); // shouldn't there be a first or get here?
              return $this->sort($data, $requestData); // don't get what this method is doing at all! Sorry!
          });
      });
      

      格式很好!

      if (!$items->first()) { // $items variable is never declated, what!?
          return back()
              ->withInput()
              ->with('status', 'Could not find anything try again!');
      }
      

      为什么这样做

      return $this->getView('index/index', $data);
      

      当你可以这样做时

      return view('index/index', $data);
      

      索引/索引 - 不是命名文件的好方法!

      }
      

      进一步提示:

      1. 格式一致
      2. 不要在一行中填写整个if语句
      3. 当方法链接分解为多行时,使其更具可读性
      4. 在具有空格的方法中分隔参数,例如:
      5. 不要这样做:

        $this->function($a,$b,$c);
        

        这样做:

        $this->function($a, $b, $c);
        
        1. 如果方法是一个单词,请不要在第一个字母上使用大写字母,例如:
        2. 不要这样做:

          $this->model->Search(...)
          

          这样做:

          $this->model->search(...)
          

          这不会阻止PHP处理它AFAIK但它的可读性更好

          1. 查看PSR-2编码标准,并尝试将其应用于您的代码中:http://www.php-fig.org/psr/psr-2/
          2. 修改2

            排序方法 逐行贯穿......

            • 以小写字母开头的名称方法:sort(),它在PHP中的常见做法
            • 在方法的参数中,在逗号和下一个参数之间留一个空格:($data, $request)

              public function Sort($data,$request) {

            • 理想情况下,您可以传递请求数据,而不是依靠方法为您处理,请考虑您的方法正在做多少不同的事情以及应该多少< / strong>正在做。

              $requestData = $request->only(['limitBy', 'sortBy', 'offset', 'limit']);
              $requestData['type'] = $request->input('type', 'items');
              
            • 请不要理解您在此处尝试使用的代码,抱歉!

            • 没有这行代码:

              whereHas($requestData['type'] == 'groups' ? 'users' : 'user'

            等同于whereHas(true/false ...),这甚至是有效的代码吗?我非常确定($requestData['type'] == 'groups')会返回true或false。

                if($requestData['type'] == 'materials' ||  $requestData['type'] == 'groups') {
                    $data->whereHas($requestData['type'] == 'groups' ? 'users' : 'user', function ($query) {
                        $query->whereHas('addresses', function($subquery) {
                            $subquery->whereId(Auth::user()->addresses()->first()->id);
                        });
                    });
                } else {
                    $data->ByExpireDate(
                        [Carbon::now(),$requestData['limiBy'] == 'today_expire' ? Carbon::tomorrow() : Carbon::now()->addWeek(1)],
                        $requestData['limiBy'] == 'today_expire' ? '1440' : '10080');
                }
            
            • 很抱歉,但我没有完成其余部分,非常困惑......

              //如果$ requestData ==&#39;限制&#39;     $ DATA-化合物其中($的RequestData [&#39;限制&#39],&#39; 1&#39); //如果$ requestData ==&#39; sortBy&#39;     $ data-&gt; orderBy($ requestData [&#39; sortBy&#39;],$ requestData [&#39; direction&#39;]); //如果$ requestData ==&#39; offset&#39;     $ DATA-&GT;跳过($的RequestData [&#39;偏移&#39;]) - &GT;取($的RequestData [&#39;限制&#39;]);     返回$ data-&gt; count()&gt; 1? $ data-&gt; paginate(15):$ data-&gt; get(); }

            getView方法

            我个人不会在这里做错误检查。如果它对你有意义,那很好!但是,Laravel允许您处理app/Exceptions/Handler.php中的例外情况,请在此处的文档中详细了解它:https://laravel.com/docs/5.2/errors#the-exception-handler

            public function getView($path,$data = null)
            {
                logger()->info(__METHOD__);
                if ( ! preg_match('/[^a-z\-_]+/', $path)) {  return 'wrong url';}//add Exception
                if ( ! view()->exists($path)) {              return 'wrong path view';}//add Exception
            
                $meta  = $this->getMeta($data);
                return view($path,compact('data','meta'));
            }
            

            尝试打开一个新问题,看看是否有任何回复和进一步的帮助。