【问题标题】:Laravel Cache:: Best PracticesLaravel 缓存:: 最佳实践
【发布时间】:2015-05-31 04:53:08
【问题描述】:

PHP 同事:

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

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

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

这是在控制器中执行此操作的初步介绍

/**
 * 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);
}

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

想法?参考?例子?

谢谢大家, 雷

【问题讨论】:

  • 缓存管理很难,这完全取决于您要缓存的内容。如果您提供一个近似值,您可能不在乎基础数据是否有些过时,相反,如果您正在缓存 ALC 之类的东西,它可能总是需要正确(然后在基础数据存储更新时刷新) .
  • 你应该在你的控制器中解耦你的逻辑,例如你可以将类型提示缓存传递给你的控制器构造函数,我还建议你为你的缓存创建存储库,这样你就可以利用 laravel 的缓存能力。

标签: php caching laravel


【解决方案1】:

许多人这样做的方式不同,但是当考虑到最佳实践时,我认为进行缓存的最佳位置是在您的存储库中。

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

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

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

//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.在 App/Repositories 中创建 GalleryRepositoryInterface.php

<?php namespace App\Repositories;

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

    public function find($id);

    public function all();
}

//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.在控制器上你可以这样做

<?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);
    }

}

【讨论】:

  • 好答案,@Digilimit。
  • 那么,不在模型中?
  • 模型也是一个好地方,但我们不要过度使用大量代码的模型。
  • 我使用 Laracogs 作为脚手架工具。它生成如下结构:控制器 -> 服务 -> 存储库 -> 模型。我关心的是:将我的代码放在哪里:验证,缓存......?服务还是存储库?为什么不是控制器? (对不起,我只是尝试熟悉设计模式,除了MVC,虽然我能理解它的理论,但我实际上并没有得到它:()。谢谢。
  • 不错的方法!只是一件小事...如果您使用Cache::remember(),我认为您不需要使用Cache::has() 检查密钥是否存在。 remember() 处理它。
【解决方案2】:

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

我建议你看看这篇文章

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

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

另一个好处是,你不仅可以通过这种方式保存数据库查询,还可以省去大量反复运行的 php 代码,例如 laravel Blade 背后的 php 代码不需要运行,它不需要't 当小部件在缓存中时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    • 2016-03-23
    • 1970-01-01
    相关资源
    最近更新 更多