SmartWiki开发日记之Laravel缓存扩展
SmartWiki简介请阅读: http://www.cnblogs.com/lifeil/p/6113323.html
因为SmartWiki的演示站点部署在阿里云上,阿里云有一个128M免费的Memcache服务,刚开始按照Memcached的配置方式配置完后,发现Laravel报错,查看日志报错位置是addServer出错,连不上阿里云的Memcache。
很无奈,于是安装阿里云的手册写了一个脚本放到服务器上,结果可以连接,也可以写入。
阿里云提供的脚本如下:
<span style="color: #000000">php </span><span style="color: #800080">$connect</span> = <span style="color: #0000ff">new</span> Memcached; <span style="color: #008000">//</span><span style="color: #008000">声明一个新的memcached链接</span> <span style="color: #800080">$connect</span>->setOption(Memcached::OPT_COMPRESSION, <span style="color: #0000ff">false</span>); <span style="color: #008000">//</span><span style="color: #008000">关闭压缩功能</span> <span style="color: #800080">$connect</span>->setOption(Memcached::OPT_BINARY_PROTOCOL, <span style="color: #0000ff">true</span>); <span style="color: #008000">//</span><span style="color: #008000">使用binary二进制协议</span> <span style="color: #800080">$connect</span>->addServer('00000000.ocs.aliyuncs.com', 11211); <span style="color: #008000">//</span><span style="color: #008000">添加OCS实例地址及端口号 //$connect->setSaslAuthData('aaaaaaaaaa, 'password'); //设置OCS帐号密码进行鉴权,如已开启免密码功能,则无需此步骤</span> <span style="color: #800080">$connect</span>->set("hello", "world"<span style="color: #000000">); </span><span style="color: #0000ff">echo</span> 'hello: ',<span style="color: #800080">$connect</span>->get("hello"<span style="color: #000000">); </span><span style="color: #008080">print_r</span>( <span style="color: #800080">$connect</span>-><span style="color: #000000">getVersion()); </span><span style="color: #800080">$connect</span>->quit();
翻看laravel的Memcached驱动,在 /vendor/laravel/framework/src/Illuminate/Cache/MemcachedConnector.php 中创建Memcached对象的代码如下:
<span style="color: #0000ff">public</span> <span style="color: #0000ff">function</span> connect(<span style="color: #0000ff">array</span> <span style="color: #800080">$servers</span><span style="color: #000000">) { </span><span style="color: #800080">$memcached</span> = <span style="color: #800080">$this</span>-><span style="color: #000000">getMemcached(); </span><span style="color: #008000">//</span><span style="color: #008000"> For each server in the array, we'll just extract the configuration and add // the server to the Memcached connection. Once we have added all of these // servers we'll verify the connection is successful and return it back.</span> <span style="color: #0000ff">foreach</span> (<span style="color: #800080">$servers</span> <span style="color: #0000ff">as</span> <span style="color: #800080">$server</span><span style="color: #000000">) { </span><span style="color: #800080">$memcached</span>-><span style="color: #000000">addServer( </span><span style="color: #800080">$server</span>['host'], <span style="color: #800080">$server</span>['port'], <span style="color: #800080">$server</span>['weight'<span style="color: #000000">] ); } </span><span style="color: #800080">$memcachedStatus</span> = <span style="color: #800080">$memcached</span>-><span style="color: #000000">getVersion(); </span><span style="color: #0000ff">if</span> (! <span style="color: #008080">is_array</span>(<span style="color: #800080">$memcachedStatus</span><span style="color: #000000">)) { </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> RuntimeException('No Memcached servers added.'<span style="color: #000000">); } </span><span style="color: #0000ff">if</span> (<span style="color: #008080">in_array</span>('255.255.255', <span style="color: #800080">$memcachedStatus</span>) && <span style="color: #008080">count</span>(<span style="color: #008080">array_unique</span>(<span style="color: #800080">$memcachedStatus</span>)) === 1<span style="color: #000000">) { </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> RuntimeException('Could not establish Memcached connection.'<span style="color: #000000">); } </span><span style="color: #0000ff">return</span> <span style="color: #800080">$memcached</span><span style="color: #000000">; }</span>
可以看到laravel的Memcached没有设置setOption方法的选项,仅仅包含最简连接建立,紧接着就调用getVersion来测试是否连通。而阿里云的演示代码是设置了关闭压缩和使用binary二进制协议的选项的。
没办法只能自己来扩展Memcached的功能实现自定义选项。laravel中扩展缓存可以使用Cache::extend来扩展。扩展代码如下:
Cache::extend('MemcachedExtend', <span style="color: #0000ff">function</span> (<span style="color: #800080">$app</span><span style="color: #000000">) { </span><span style="color: #800080">$memcached</span> = <span style="color: #800080">$this</span>->createMemcached(<span style="color: #800080">$app</span><span style="color: #000000">); </span><span style="color: #008000">//</span><span style="color: #008000"> 从配置文件中读取缓存前缀</span> <span style="color: #800080">$prefix</span> = <span style="color: #800080">$app</span>['config']['cache.prefix'<span style="color: #000000">]; </span><span style="color: #008000">//</span><span style="color: #008000"> 创建 MemcachedStore 对象</span> <span style="color: #800080">$store</span> = <span style="color: #0000ff">new</span> MemcachedStore(<span style="color: #800080">$memcached</span>, <span style="color: #800080">$prefix</span><span style="color: #000000">); </span><span style="color: #008000">//</span><span style="color: #008000"> 创建 Repository 对象,并返回</span> <span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span> Repository(<span style="color: #800080">$store</span><span style="color: #000000">); });</span>
<span style="color: #008000">/*</span><span style="color: #008000">* * 创建Memcached对象 * @param $app * @return mixed </span><span style="color: #008000">*/</span> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">function</span> createMemcached(<span style="color: #800080">$app</span><span style="color: #000000">) { </span><span style="color: #008000">//</span><span style="color: #008000"> 从配置文件中读取 Memcached 服务器配置</span> <span style="color: #800080">$servers</span> = <span style="color: #800080">$app</span>['config']['cache.stores.MemcachedExtend.servers'<span style="color: #000000">]; </span><span style="color: #008000">//</span><span style="color: #008000"> 利用 Illuminate\Cache\MemcachedConnector 类来创建新的 Memcached 对象</span> <span style="color: #800080">$memcached</span> = <span style="color: #0000ff">new</span><span style="color: #000000"> \Memcached; </span><span style="color: #0000ff">foreach</span> (<span style="color: #800080">$servers</span> <span style="color: #0000ff">as</span> <span style="color: #800080">$server</span><span style="color: #000000">) { </span><span style="color: #800080">$memcached</span>-><span style="color: #000000">addServer( </span><span style="color: #800080">$server</span>['host'], <span style="color: #800080">$server</span>['port'], <span style="color: #800080">$server</span>['weight'<span style="color: #000000">] ); } </span><span style="color: #008000">//</span><span style="color: #008000"> 如果服务器上的 PHP Memcached 扩展支持 SASL 认证</span> <span style="color: #0000ff">if</span> (<span style="color: #008080">ini_get</span>('memcached.use_sasl') && <span style="color: #0000ff">isset</span>(<span style="color: #800080">$app</span>['config']['cache.storess.MemcachedExtend.memcached_user']) && <span style="color: #0000ff">isset</span>(<span style="color: #800080">$app</span>['config']['cache.storess.MemcachedExtend.memcached_pass'<span style="color: #000000">])) { </span><span style="color: #008000">//</span><span style="color: #008000"> 从配置文件中读取 sasl 认证用户名</span> <span style="color: #800080">$user</span> = <span style="color: #800080">$app</span>['config']['cache.storess.MemcachedExtend.memcached_user'<span style="color: #000000">]; </span><span style="color: #008000">//</span><span style="color: #008000"> 从配置文件中读取 sasl 认证密码</span> <span style="color: #800080">$pass</span> = <span style="color: #800080">$app</span>['config']['cache.storess.MemcachedExtend.memcached_pass'<span style="color: #000000">]; </span><span style="color: #008000">//</span><span style="color: #008000"> 指定用于 sasl 认证的账号密码</span> <span style="color: #800080">$memcached</span>->setSaslAuthData(<span style="color: #800080">$user</span>, <span style="color: #800080">$pass</span><span style="color: #000000">); } </span><span style="color: #008000">//</span><span style="color: #008000">扩展</span> <span style="color: #0000ff">if</span> (<span style="color: #0000ff">isset</span>(<span style="color: #800080">$app</span>['config']['cache.stores.MemcachedExtend.options'<span style="color: #000000">])) { </span><span style="color: #0000ff">foreach</span> (<span style="color: #800080">$app</span>['config']['cache.stores.MemcachedExtend.options'] <span style="color: #0000ff">as</span> <span style="color: #800080">$key</span> => <span style="color: #800080">$option</span><span style="color: #000000">) { </span><span style="color: #800080">$memcached</span>->setOption(<span style="color: #800080">$key</span>, <span style="color: #800080">$option</span><span style="color: #000000">); } } </span><span style="color: #800080">$memcachedStatus</span> = <span style="color: #800080">$memcached</span>-><span style="color: #000000">getVersion(); </span><span style="color: #0000ff">if</span> (! <span style="color: #008080">is_array</span>(<span style="color: #800080">$memcachedStatus</span><span style="color: #000000">)) { </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> RuntimeException('No Memcached servers added.'<span style="color: #000000">); } </span><span style="color: #0000ff">if</span> (<span style="color: #008080">in_array</span>('255.255.255', <span style="color: #800080">$memcachedStatus</span>) && <span style="color: #008080">count</span>(<span style="color: #008080">array_unique</span>(<span style="color: #800080">$memcachedStatus</span>)) === 1<span style="color: #000000">) { </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> RuntimeException('Could not establish Memcached connection.'<span style="color: #000000">); } </span><span style="color: #0000ff">return</span> <span style="color: #800080">$memcached</span><span style="color: #000000">; }</span>
网上有流传的laravel缓存扩展的文章,其中对配置读取在5.2以上版本不适用。
缓存扩展后的代码是需要创建一个ServiceProvider来注册服务提供者。服务提供者是Laravel应用启动的中心,你自己的应用以及所有Laravel的核心服务都是通过服务提供者启动。
但是,我们所谓的“启动”指的是什么?通常,这意味着注册事物,包括注册服务容器绑定、事件监听器、中间件甚至路由。服务提供者是应用配置的中心。
如果你打开Laravel自带的config/app.php文件,将会看到一个providers数组,这里就是应用所要加载的所有服务提供者类,当然,其中很多是延迟加载的,也就是说不是每次请求都会被加载,只有真的用到它们的时候才会加载。
所有的服务提供者都继承自Illuminate\Support\ServiceProvider类。大部分服务提供者都包含两个方法: register 和 boot 。在register方法中,你唯一要做的事情就是绑事物到服务容器,不要尝试在其中注册事件监听器,路由或者任何其它功能。
通过Artisan命令make:provider可以简单生成一个新的提供者:
php artisan <span style="color: #0000ff">make</span>:provider MemcachedExtendServiceProvider
所有服务提供者都是通过配置文件config/app.php中进行注册,该文件包含了一个列出所有服务提供者名字的providers数组,默认情况下,其中列出了所有核心服务提供者,这些服务提供者启动Laravel核心组件,比如邮件、队列、缓存等等。
要注册你自己的服务提供者,只需要将其追加到该数组中即可:
<span style="color: #800000">'</span><span style="color: #800000">providers</span><span style="color: #800000">'</span> =><span style="color: #000000"> [ SmartWiki\Providers\MemcachedExtendServiceProvider::class </span><span style="color: #008000">//</span><span style="color: #008000">在providers节点添加实现的provider</span> ]
同时在config/cache.php中配置Memcached配置:
'MemcachedExtend' =><span style="color: #000000"> [ </span>'driver' => 'MemcachedExtend', 'servers' =><span style="color: #000000"> [ [ </span>'host' => env('MEMCACHED_EXTEND_HOST', '127.0.0.1'), 'port' => env('MEMCACHED_EXTEND_PORT', 11211), 'weight' => 100,<span style="color: #000000"> ]</span>,<span style="color: #000000"> ]</span>, 'options' =><span style="color: #000000"> [ \Memcached</span>::OPT_BINARY_PROTOCOL => <span style="color: #0000ff">true</span>,<span style="color: #000000"> \Memcached</span>::OPT_COMPRESSION => <span style="color: #0000ff">false</span><span style="color: #000000"> ] ]</span>
如果需要把Session也储存到我们扩展的缓存中还需要调用Session::extend来扩展我们的Session储存:
Session::extend('MemcachedExtend',<span style="color: #0000ff">function</span> (<span style="color: #800080">$app</span><span style="color: #000000">){ </span><span style="color: #800080">$memcached</span> = <span style="color: #800080">$this</span>->createMemcached(<span style="color: #800080">$app</span><span style="color: #000000">); </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span> MemcachedSessionHandler(<span style="color: #800080">$memcached</span><span style="color: #000000">); });</span>
之后再.env中就可以配置我们扩展后的缓存了。完整代码如下:


<span style="color: #000000">php namespace SmartWiki\Providers; </span><span style="color: #0000ff">use</span><span style="color: #000000"> Illuminate\Cache\Repository; </span><span style="color: #0000ff">use</span><span style="color: #000000"> Illuminate\Cache\MemcachedStore; </span><span style="color: #0000ff">use</span><span style="color: #000000"> Illuminate\Support\ServiceProvider; </span><span style="color: #0000ff">use</span><span style="color: #000000"> Cache; </span><span style="color: #0000ff">use</span><span style="color: #000000"> Session; </span><span style="color: #0000ff">use</span><span style="color: #000000"> Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler; </span><span style="color: #0000ff">use</span><span style="color: #000000"> RuntimeException; </span><span style="color: #0000ff">class</span> MemcachedExtendServiceProvider <span style="color: #0000ff">extends</span><span style="color: #000000"> ServiceProvider { </span><span style="color: #008000">/*</span><span style="color: #008000">* * Bootstrap the application services. * * @return void </span><span style="color: #008000">*/</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">function</span><span style="color: #000000"> boot() { Cache</span>::extend('MemcachedExtend', <span style="color: #0000ff">function</span> (<span style="color: #800080">$app</span><span style="color: #000000">) { </span><span style="color: #800080">$memcached</span> = <span style="color: #800080">$this</span>->createMemcached(<span style="color: #800080">$app</span><span style="color: #000000">); </span><span style="color: #008000">//</span><span style="color: #008000"> 从配置文件中读取缓存前缀</span> <span style="color: #800080">$prefix</span> = <span style="color: #800080">$app</span>['config']['cache.prefix'<span style="color: #000000">]; </span><span style="color: #008000">//</span><span style="color: #008000"> 创建 MemcachedStore 对象</span> <span style="color: #800080">$store</span> = <span style="color: #0000ff">new</span> MemcachedStore(<span style="color: #800080">$memcached</span>, <span style="color: #800080">$prefix</span><span style="color: #000000">); </span><span style="color: #008000">//</span><span style="color: #008000"> 创建 Repository 对象,并返回</span> <span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span> Repository(<span style="color: #800080">$store</span><span style="color: #000000">); }); Session</span>::extend('MemcachedExtend',<span style="color: #0000ff">function</span> (<span style="color: #800080">$app</span><span style="color: #000000">){ </span><span style="color: #800080">$memcached</span> = <span style="color: #800080">$this</span>->createMemcached(<span style="color: #800080">$app</span><span style="color: #000000">); </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span> MemcachedSessionHandler(<span style="color: #800080">$memcached</span><span style="color: #000000">); }); } </span><span style="color: #008000">/*</span><span style="color: #008000">* * Register the application services. * * @return void </span><span style="color: #008000">*/</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">function</span><span style="color: #000000"> register() { </span><span style="color: #008000">// </span><span style="color: #000000"> } </span><span style="color: #008000">/*</span><span style="color: #008000">* * 创建Memcached对象 * @param $app * @return mixed </span><span style="color: #008000">*/</span> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">function</span> createMemcached(<span style="color: #800080">$app</span><span style="color: #000000">) { </span><span style="color: #008000">//</span><span style="color: #008000"> 从配置文件中读取 Memcached 服务器配置</span> <span style="color: #800080">$servers</span> = <span style="color: #800080">$app</span>['config']['cache.stores.MemcachedExtend.servers'<span style="color: #000000">]; </span><span style="color: #008000">//</span><span style="color: #008000"> 利用 Illuminate\Cache\MemcachedConnector 类来创建新的 Memcached 对象</span> <span style="color: #800080">$memcached</span> = <span style="color: #0000ff">new</span><span style="color: #000000"> \Memcached; </span><span style="color: #0000ff">foreach</span> (<span style="color: #800080">$servers</span> <span style="color: #0000ff">as</span> <span style="color: #800080">$server</span><span style="color: #000000">) { </span><span style="color: #800080">$memcached</span>-><span style="color: #000000">addServer( </span><span style="color: #800080">$server</span>['host'], <span style="color: #800080">$server</span>['port'], <span style="color: #800080">$server</span>['weight'<span style="color: #000000">] ); } </span><span style="color: #008000">//</span><span style="color: #008000"> 如果服务器上的 PHP Memcached 扩展支持 SASL 认证</span> <span style="color: #0000ff">if</span> (<span style="color: #008080">ini_get</span>('memcached.use_sasl') && <span style="color: #0000ff">isset</span>(<span style="color: #800080">$app</span>['config']['cache.storess.MemcachedExtend.memcached_user']) && <span style="color: #0000ff">isset</span>(<span style="color: #800080">$app</span>['config']['cache.storess.MemcachedExtend.memcached_pass'<span style="color: #000000">])) { </span><span style="color: #008000">//</span><span style="color: #008000"> 从配置文件中读取 sasl 认证用户名</span> <span style="color: #800080">$user</span> = <span style="color: #800080">$app</span>['config']['cache.storess.MemcachedExtend.memcached_user'<span style="color: #000000">]; </span><span style="color: #008000">//</span><span style="color: #008000"> 从配置文件中读取 sasl 认证密码</span> <span style="color: #800080">$pass</span> = <span style="color: #800080">$app</span>['config']['cache.storess.MemcachedExtend.memcached_pass'<span style="color: #000000">]; </span><span style="color: #008000">//</span><span style="color: #008000"> 指定用于 sasl 认证的账号密码</span> <span style="color: #800080">$memcached</span>->setSaslAuthData(<span style="color: #800080">$user</span>, <span style="color: #800080">$pass</span><span style="color: #000000">); } </span><span style="color: #008000">//</span><span style="color: #008000">扩展</span> <span style="color: #0000ff">if</span> (<span style="color: #0000ff">isset</span>(<span style="color: #800080">$app</span>['config']['cache.stores.MemcachedExtend.options'<span style="color: #000000">])) { </span><span style="color: #0000ff">foreach</span> (<span style="color: #800080">$app</span>['config']['cache.stores.MemcachedExtend.options'] <span style="color: #0000ff">as</span> <span style="color: #800080">$key</span> => <span style="color: #800080">$option</span><span style="color: #000000">) { </span><span style="color: #800080">$memcached</span>->setOption(<span style="color: #800080">$key</span>, <span style="color: #800080">$option</span><span style="color: #000000">); } } </span><span style="color: #800080">$memcachedStatus</span> = <span style="color: #800080">$memcached</span>-><span style="color: #000000">getVersion(); </span><span style="color: #0000ff">if</span> (! <span style="color: #008080">is_array</span>(<span style="color: #800080">$memcachedStatus</span><span style="color: #000000">)) { </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> RuntimeException('No Memcached servers added.'<span style="color: #000000">); } </span><span style="color: #0000ff">if</span> (<span style="color: #008080">in_array</span>('255.255.255', <span style="color: #800080">$memcachedStatus</span>) && <span style="color: #008080">count</span>(<span style="color: #008080">array_unique</span>(<span style="color: #800080">$memcachedStatus</span>)) === 1<span style="color: #000000">) { </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> RuntimeException('Could not establish Memcached connection.'<span style="color: #000000">); } </span><span style="color: #0000ff">return</span> <span style="color: #800080">$memcached</span><span style="color: #000000">; } }</span>
SmartWiki官网: https://www.iminho.me
SmartWiki源码: https://github.com/lifei6671/SmartWiki

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)