Laravel框架中落实接受Ali云ACE缓存服务_php本领_脚

作者:编程技术

理解原理

虽然解决了问题,但还是不知道其原理究竟是怎样的,带着这样的疑问我继续查看源码,最终找到了相应的内容。

  • session不是实时落地的,也就是说当你调用session(['id' => $id])时,id并没有被真正存入redis中,而是缓存在 IlluminateSessionStore单例的attributes属性中,可以查看其put方法,代码如下:
    ```php
    public function put($key, $value = null)
    {
    if (! is_array($key)) {
    $key = [$key => $value];
    }

      foreach ($key as $arrayKey => $arrayValue) {
          Arr::set($this->attributes, $arrayKey, $arrayValue);
      }
    

    }
    ```

  • IlluminateSessionMiddlewareStartSession在执行时,回自动加载redis中已经实例化的数据,并覆盖IlluminateSessionStore单例中的attributes属性,所以这就导致我们一直取到的都是redis中的session数据。加载覆盖的代码如下:

    protected function loadSession()
    {
        $this->attributes = array_merge($this->attributes, $this->readFromHandler());
    }
    protected function readFromHandler()
    {
        if ($data = $this->handler->read($this->getId())) {
            $data = @unserialize($this->prepareForUnserialize($data));
    
            if ($data !== false && ! is_null($data) && is_array($data)) {
                return $data;
            }
        }
    
        return [];
    }
    

其中的readFromHandler方法就是获取redis中的session数据。

Laravel 4 内置的 Memcached 缓存驱动,实现的流程是这样的:

框架版本

Laravel 5.4

如何扩展 Laravel 的缓存驱动

问题

先来描述下问题,我在我们项目基础的Middleware中,加入session操作,存入了一个值,再在Controller中取出使用,大致代码如下:

// Middleware
public function handle($request, Closure $next)
{
    $id = Redis::get('id');
    session(['id' => $id]);
    return $next($request);
}

// Controller
public function index()
{
    $id = session('id');
    return ['id' => $id];
}

假设reids中的id是1,这一次访问index这个action,返回的是1,当你将redisid的值改成2时,在访问,发现返回的还是1,而且之后的访问也都是1。这里说明一下session使用的是redis

在控制台创建了缓存空间之后,会有唯一的“缓存空间名称”,然后通过 Alibaba::Cache 来获得 Cache 对象。以下就是实现 ACE 缓存服务驱动的步骤:

解决问题

看到这样神奇的结果,百思不得其解。于是打开Xdebug,开始调试。经过多次调试,发现在执行完
IlluminateSessionMiddlewareStartSession这个Middleware后,session里面的值就变回1了,在之前都是2。然后想到会不会我们的MiddlewareStartSession之前执行造成的,将我们的Middleware移到StartSession之后,发现果然可以了,app/Http/Kernel.php中的代码如下:

protected $middlewareGroups = [
    'web' => [
        IlluminateCookieMiddlewareEncryptCookies::class,
        IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,
        IlluminateSessionMiddlewareStartSession::class,
        IlluminateViewMiddlewareShareErrorsFromSession::class,
        IlluminateRoutingMiddlewareSubstituteBindings::class,
        AppHttpMiddlewareOurMiddleware::class,
    ]
];

其中的OurMiddleware是我们自己写的Middleware,之前是放在最上面的,$next($request)之前的代码的执行顺序是从上到下的,如果OurMiddleware中有些内容是必须在最开始的,可以考虑分成两个Middleware

1.创建一个标准 Memcached 类的新对象2.用上一步创建的 Memcached 对象创建一个实现了 IlluminateCacheStoreInterface 接口的 IlluminateCacheMemecachedStore 对象。3.用上一步创建的 MemcachedStore 对象创建一个 IlluminateCacheRepository 对象。

这两天遇到了一个很奇怪的问题,更新sessionsession的值不变。经过一番追查,终于找到问题,并搞明白了原理。写这篇博客记录下。

ACE 的缓存服务

后记

其实这不是Laravel session的坑,是我自己踩坑,原谅我是个标题党

阿里云 ACE 的缓存服务,跟默认的 OCS 有所不同:

1.在 app 的同级目录创建目录 src/Ace。2.打开 composer.json 文件,修改 autoload 节,在 classmap 下面用 psr-0 或者 psr-4 来自动加载文件。复制代码 代码如下:"autoload": { "classmap": [ // autoload class ], "psr-4": { "Ace\": "src/Ace" }},

使用和限制

AceMemcachedStore类已经创建好了,接下来在 bootstrap/start.php 文件中扩展 Cache:

这段代码比较简单,不过要特别注意一下 get 方法的实现。标准 memcached 以及 ACE 的缓存对象的 get 方法都是key有效时返回对应的缓存值,否则返回false,而在 Laravel 4 中,是通过检测 get 方法返回的是否 null 来做判断,所以这里需要处理一下,返回缓存值或者null。

指定系统使用 'ace' 作为缓存驱动:打开 app/config/cache.php,找到 'driver' => '...' 所在行,修改为:'driver' => 'ace'.

所以我们在扩展自定义的 Cache 驱动时,根据自己的情况,选择上面的某一个步骤自定义,最终还是要返回 IlluminateCacheRepository 对象。比如上一篇文章中,我就是在第一步,创建标准 Memcached 对象之后,通过 setSaslAuthData() 方法设定 OCS 需要的用户名密码。之后第2步、第3步并不需要自定义。

第一步,修改配置文件。打开 app/config/cache.php,在最后增加一行:复制代码 代码如下:// 指定缓存空间名称'ace' => 'lblog-cache',第二步,为了方便,把自己的类文件放在 src/Ace 目录下,使用 Ace 作为命名空间。

之前我写了一篇在 Laravel 4 框架中使用阿里云 OCS 缓存的文章,介绍了如何通过扩展 Laravel 4 来支持需要 SASL 认证的阿里云 OCS 缓存服务。有网友问我,ACE 的缓存怎么在 Laravel 4 中使用。我本来觉得应该可以完全用相同的办法,后来自己尝试的时候才发现,ACE 的缓存差别非常大。所以再写一篇,介绍一下如何在 Laravel 框架中使用阿里云 ACE 的缓存服务。

在 Laravel 4 中使用 Cache::get, Cache::put($key, $value, $minutes) 这样的代码时,实际上是访问 实例化的 IlluminateCacheRepository, 所以我们通过 Cache::extend 方法扩展自定义缓存驱动时,同样应该返回一个 IlluminateCacheRepository 对象。

通过以上操作,就可以在 Laravel 4 中调用 ACE 的缓存服务,使用上与平常的用法完全一致,比如:复制代码 代码如下:// 添加缓存,有效时间10分钟Cache::put('my_key', 'my value', 10);// 读取缓存Cache::get// 判断缓存是否存在Cache::has// 数据查询缓存$users = DB::table->remember;

下面来看具体的代码实现:

但是由于 ACE 缓存对象本身的限制,只能删除指定 key 的缓存对象,不能遍历、全量操作,因此 Cache::flush() 方法就不能使用。在上面的 AceMemcachedStore 对象中,flush 方法没有做任何操作,只是返回 false.

创建 src/Ace/AceMemcachedStore.php 文件,代码如下:复制代码 代码如下:memcached = Alibaba::Cache; $this->prefix = strlen > 0 ? $prefix.':' : ''; } /** * Retrieve an item from the cache by key. * * @param string $key * @return mixed */ public function get { $value = $this->memcached->get; if && $value === false) { return null; } return $value; } /** * Store an item in the cache for a given number of minutes. * * @param string $key * @param mixed $value * @param int $minutes * @return boolean */ public function put($key, $value, $minutes) { return $this->memcached->set($this->prefix.$key, $value, $minutes); } /** * Increment the value of an item in the cache. * * @param string $key *Laravel框架中落实接受Ali云ACE缓存服务_php本领_脚本之家分分快三计划。 @param mixed $value * @return boolean */ public function increment { return $this->memcached->increment($this->prefix.$key, $value); } /** * Decrement the value of an item in the cache. * * @param string $key * @param mixed $value * @return boolean */ public function decrement { return $this->memcached->decrement($this->prefix.$key, $value); } /** * Store an item in the cache indefinitely. * * @param string $key * @param mixed $value * @return boolean */ public function forever { return $this->memcached->set; } /** * Remove an item from the cache. * * @param string $key * @return boolean */ public function forget { return $this->memcached->delete; } /** * Remove all items from the cache. * * @return void */ public function flush() { //$this->memcached->flush(); return false; } public function getMemcached() { return $this->memcached; } /** * Get the cache key prefix. * * @return string */ public function getPrefix() { return $this->prefix; }}

所以,这次第一步得到的不是标准 Memcached 对象,因此就不能创建 IlluminateCacheMemcachedStore 对象。需要自己实现 IlluminateCacheStoreInterface 接口。

打开 bootstrap/start.php, 添加以下代码:复制代码 代码如下:// 扩展名为 ace 的缓存驱动Cache::extend{ // 从 app/config/cache.php 文件中读取 "ace" 的值 $space = $app['config']['cache.ace']; // 从 app/config/cache.php 文件中读取 "prefix" 的值 $prefix = $app['config']['cache.prefix']; // 创建 AceAceMemcachedStore 对象 $store = new AceAceMemcachedStore; // 创建并返回 IlluminateCacheRepository 对象 return new IlluminateCacheRepository;

1.为了方便修改,我在配置文件 app/config/cache.php 中增加一个名为 ace 的键,存储缓存空间名称。2.然后创建一个 AceMemcachedStore 类,这个类实现 IlluminateCacheStoreInterface 接口。3.最后,用 AceMemcachedStore 对象来创建 IlluminateCacheRepository 对象。

1.通过 Alibaba::Cache() 方法获得 Cache 对象。2.ACE 的 Cache 对象与标准 Memcached 对象不同,支持的方法有限。

编码实现自定义 ACE 缓存驱动:

本文由分分快三计划发布,转载请注明来源

关键词: 分分快三计划 缓存 阿里 脚本 之家