让laravel支持memcache

一条评论

2014 年 01 月 09 日 at 下午 10:13分类:PHP

默认laravel框架在cache和session方面是不支持memcache的,他提供了一个memcache升级版memcached,但是我们在本地开发的时候,这个拓展很难找到,而memcache却很方便,于是今天看了下源代码,修改了部分东西,让laravel在cache和session方面完美支持memcache,具体修改如下:
1:找到这个文件:
Laravel/vendor/laravel/framework/src/Illuminate/Session/SessionManager.php
这是session的一个管理器文件。
我们增加以下代码:

/**
	 * Create an instance of the Memcached session driver.
	 *
	 * @return \Illuminate\Session\Store
	 */
	protected function createMemcacheDriver()
	{
		return $this->createCacheBased('memcache');
	}

这个主要是正佳一个memcahce的缓存支持,
我们知道在laravel中个,memcahce的驱动逻辑很多都是走的是cache的驱动逻辑实现的,那么接下来我们就要修改cache这块了
2:找到文件:
Laravel/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php
在该文件中增加以下代码:

/**
	 * Create an instance of the Memcache cache driver.
	 *
	 * @return \Illuminate\Cache\MemcachedStore
	 */
	protected function createMemcacheDriver()
	{
		$servers = $this->app['config']['cache.memcached'];

		$memcache = $this->app['memcache.connector']->connect($servers);

		return $this->repository(new MemcacheStore($memcache, $this->getPrefix()));
	}

其实session的memcahce最终的驱动走向还是走这个方法的,那么我们在这个方法中看到了”$this->app['memcache.connector']->”这个代码,
那么这连接器又是在哪里存储进app这个属性里面的呢?
它其实是在我们启动app时,版定相关的serviceProvider的时候注册进去的,那么接下来我们找到文件:
Laravel/vendor/laravel/framework/src/Illuminate/Cache/CacheServiceProvider.php
修改如下:

/**
	 * Register the service provider.
	 *
	 * @return void
	 */
	public function register()
	{
		$this->app['cache'] = $this->app->share(function($app)
		{
			return new CacheManager($app);
		});

		$this->app['memcached.connector'] = $this->app->share(function()
		{
			return new MemcachedConnector;
		});
                // 增加以下代码
		$this->app['memcache.connector'] = $this->app->share(function()
		{
			return new MemcacheConnector;
		});

		$this->registerCommands();
	}

我们看到这个闭包函数中返回了MemcacheContector的对象,那么这个class怎么弄呢?我们创建个吧
文件地址:Laravel/vendor/laravel/framework/src/Illuminate/Cache/MemcacheConnector.php
文件代码如下:其实是拿MemcachedContector的代码改的

<?php namespace Illuminate\Cache;

use Memcache;

class MemcacheConnector {

	/**
	 * Create a new Memcached connection.
	 *
	 * @param array  $servers
	 * @return \Memcache
	 */
	public function connect(array $servers)
	{
		$memcache = $this->getMemcache();

		// For each server in the array, we'll just extract the configuration and add
		// the server to the Memcache connection. Once we have added all of these
		// servers we'll verify the connection is successful and return it back.
		foreach ($servers as $server)
		{
			$memcache->addServer($server['host'], $server['port'], $server['weight']);
		}

		if ($memcache->getVersion() === false)
		{
			throw new \RuntimeException("Could not establish Memcache connection.");
		}

		return $memcache;
	}

	/**
	 * Get a new Memcache instance.
	 *
	 * @return \Memcached
	 */
	protected function getMemcache()
	{
		return new Memcache;
	}
}

那么按照第二步的流程这个文件会执行connect的方法,执行完成之后返回一个Memcache的对象,
这时候第二步那里根据这边来创建了一个MemcacheStore的存储器,那么这个文件也是需要我们创建,很简单,拿一份memcachedSrote改一下就好了。
文件地址:Laravel/vendor/laravel/framework/src/Illuminate/Cache/MemcacheStore.php
拷贝过来之后我们要改以下几个地方:
1:应用的类名:


use Memcache;

class MemcacheStore implements StoreInterface {

构造函数的类型处:

public function __construct(Memcache $memcache, $prefix = '')
	{
		$this->memcache = $memcache;
		$this->prefix = strlen($prefix) > 0 ? $prefix.':' : '';
	}

get方法的修改,我们直接返回值就可以了。

/**
	 * Retrieve an item from the cache by key.
	 *
	 * @param  string  $key
	 * @return mixed
	 */
	public function get($key)
	{
		return $this->memcache->get($this->prefix.$key);
	}

put方法要修改下:

/**
	 * Store an item in the cache for a given number of minutes.
	 *
	 * @param  string  $key
	 * @param  mixed   $value
	 * @param  int     $minutes
	 * @return void
	 */
	public function put($key, $value, $minutes)
	{
		$compress = is_bool($value) || is_int($value) || is_float($value) ? false : MEMCACHE_COMPRESSED;

		$this->memcache->set($this->prefix.$key, $value, $compress, $minutes * 60);
	}

这样子就基本改完了。
那么我么在用cache和session的时候就可以使用memcahe作为驱动了,那么这个memcache的配置信息怎么办呢?
还是跟memcached的配置一样,在cache.php的memcached索引中配置即可。

这里说明下,上篇文章中说到的关于redis无法使用指定的服务器的问题,实际上在cache和session.php的配置文件中,都有一个connection的索引
配置项,那么只要在这里指定就可以了,比如:connection=>session,就说明是用database.php的redis的session这个key指定的配置信息了。