Laravel 缓存::最佳实践

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29290898/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 11:14:06  来源:igfitidea点击:

Laravel Cache:: Best Practices

phpcachinglaravel

提问by Ray Paseur

PHP Colleagues:

PHP同事:

This question relates to best practices for using Laravel Cache.

这个问题与使用 Laravel Cache 的最佳实践有关。

The central objective is to reduce the number of accesses to the database for all the usual performance-related reasons. The application is a read-intensive news site with perhaps a dozen controllers at most, mostly resource-type.

中心目标是为了所有与性能相关的常见原因减少对数据库的访问次数。该应用程序是一个阅读密集型新闻站点,最多可能有十几个控制器,主要是资源类型。

Are there any documented best practices for the application design? It seems obvious to me that since Cache:: is a one-line statement, it's easy to drop this into the controllers -- either return the cached data or call the model and cache the results. And invalidate the cache (maybe with an eager reload) when requests update the model. But is that a good practice?

是否有任何记录在案的应用程序设计最佳实践?对我来说很明显,因为 Cache:: 是一个单行语句,很容易将它放到控制器中——要么返回缓存的数据,要么调用模型并缓存结果。并在请求更新模型时使缓存无效(可能需要急切地重新加载)。但这是一个好习惯吗?

Here's a first look at doing this in the controller

这是在控制器中执行此操作的第一眼

/**
 * Retrieve listing of the gallery resource.
 *
 * @uses GET /gallery to return all image_collections.
 *
 * @param int $id The gallery id
 *
 * @return Response - Contains a HTTP code and a list of articles.
 */
public function index()
{
    $response_data = array();
    $response_code = 200;

    // TRY TO RETURN A CACHED RESPONSE
    $cache_key = "gallery_index";
    $response_data = Cache::get($cache_key, null);

    // IF NO CACHED RESPONSE, QUERY THE DATABASE
    if (!$response_data) {
        try {
            $response_data['items'] = $this->gallery->all();
            Cache::put($cache_key, $response_data, Config::get('app.gallery_cache_minutes'));
        } catch (PDOException $ex) {
            $response_code = 500;
            $response_data['error'] = ErrorReporter::raiseError($ex->getCode());
        }
    }

    return Response::json($response_data, $response_code);
}

I've heard the suggestion that you could use Laravel Route Filters to cache the responses, but I can't quite get my head around the idea.

我听说您可以使用 Laravel 路由过滤器来缓存响应的建议,但我无法完全理解这个想法。

Thoughts? References? Examples?

想法?参考?例子?

Thanks to all, Ray

谢谢大家,雷

回答by Emeka Mbah

Many people do this differently but when best practices is a concern I believe the best place to do caching is in your repository.

许多人以不同的方式执行此操作,但是当考虑最佳实践时,我认为进行缓存的最佳位置是在您的存储库中。

Your controller shouldn't know too much about the data source I mean whether its coming from cache or coming from database.

您的控制器不应该对数据源了解太多,我的意思是它是来自缓存还是来自数据库。

Caching in controller doesn't support DRY (Don't Repeat Yourself) approach, because you find yourself duplicating your code in several controllers and methods thereby making scripts difficult to maintain.

控制器中的缓存不支持 DRY(不要重复自己)方法,因为您发现自己在多个控制器和方法中复制代码,从而使脚本难以维护。

So for me this is how I roll in Laravel 5 not so different if are using laravel 4:

所以对我来说,这就是我在 Laravel 5 中滚动的方式,如果使用 Laravel 4,则没有太大区别:

//1. Create GalleryEloquentRepository.php in App/Repositories

//1. 在 App/Repositories 中创建 GalleryEloquentRepository.php

<?php namespace App\Repositories;

use App\Models\Gallery;
use \Cache;

/**
 * Class GalleryEloquentRepository
 * @package App\Repositories
 */
class GalleryEloquentRepository implements GalleryRepositoryInterface
{

    public function all()
    {
        return Cache::remember('gallerys', $minutes='60', function()
        {
            return Gallery::all();
        });
    }


    public function find($id)
    {
        return Cache::remember("gallerys.{$id}", $minutes='60', function() use($id)
        {
            if(Cache::has('gallerys')) return Cache::has('gallerys')->find($id); //here am simply trying Laravel Collection method -find

            return Gallery::find($id);
        });
    }

}

//2. Create GalleryRepositoryInterface.php in App/Repositories

//2. 在 App/Repositories 中创建 GalleryRepositoryInterface.php

<?php namespace App\Repositories;

/**
 * Interface GalleryRepositoryInterface
 * @package App\Repositories
 */
interface GalleryRepositoryInterface
{

    public function find($id);

    public function all();
}

//3. Create RepositoryServiceProvider.php in App/Providers

//3. 在 App/Providers 中创建 RepositoryServiceProvider.php

<?php namespace App\Providers;

use Illuminate\Support\ServiceProvider;

/**
 * Class RepositoryServiceProvider
 * @package App\Providers
 */
class RepositoryServiceProvider extends ServiceProvider
{

    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    //protected $defer = true;

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {

        $this->app->bind(
            'App\Repositories\GalleryRepositoryInterface',
            'App\Repositories\GalleryEloquentRepository'
        );
    }
}

//4. At the controller you can do this

//4. 在控制器上,您可以执行此操作

<?php namespace App\Http\Controllers;

use \View;
use App\Repositories\GalleryRepositoryInterface;

class GalleryController extends Controller {

    public function __construct(GalleryRepositoryInterface $galleryInterface)
    {
        $this->galleryInterface = $galleryInterface;

    }


    public function index()
    {
        $gallery = $this->galleryInterface->all();

        return $gallery ? Response::json($gallery->toArray()) : Response::json($gallery,500);
    }

}

回答by Iman Ghafoori

Of course there are techniques that you can avoid putting cache logic within your controllers and hand it off to some third party packages to manage the caching for you.

当然,有些技术可以避免将缓存逻辑放入控制器中,并将其交给一些第三方包来为您管理缓存。

I recommend you to take a look at this article

我建议你看看这篇文章

https://github.com/imanghafoori1/laravel-widgetize

https://github.com/imanghafoori1/laravel-widgetize

This way you can organize your page partials into well defined and self cached widgetsclasses. so you will have granular control for cache configs, and you only have to set the "configs"(and not the caching logic). like "cache tags", "expiration period" and etc. The cache logic is written by some one else for you and extracted out into a well unit tested package. so it does not pollute you code.

通过这种方式,您可以将页面部分组织成定义明确且自缓存的widgets类。因此您将对缓存配置进行精细控制,并且您只需设置“配置”(而不是缓存逻辑)。像“缓存标签”,“到期时间”等。缓存逻辑是由其他人为您编写的,并提取到一个经过良好单元测试的包中。所以它不会污染你的代码。

The other advantage is that not only you save database queries in this way but you also save a lot of php code from running over and over again, for example the php code behind laravel blade does not need to be run and it doesn't when the widget is within the cache.

另一个好处是不仅可以通过这种方式保存数据库查询,而且还可以节省大量的 php 代码,以免一遍又一遍地运行,例如不需要运行 Laravel Blade 后面的 php 代码,也不需要运行小部件在缓存中。