SmartWiki開發(fā)日記之Laravel緩存擴展
Dec 05, 2016 pm 01:26 PMSmartWiki簡介請閱讀:?http://www.cnblogs.com/lifeil/p/6113323.html
因為SmartWiki的演示站點部署在阿里云上,阿里云有一個128M免費的Memcache服務(wù),剛開始按照Memcached的配置方式配置完后,發(fā)現(xiàn)Laravel報錯,查看日志報錯位置是addServer出錯,連不上阿里云的Memcache。
很無奈,于是安裝阿里云的手冊寫了一個腳本放到服務(wù)器上,結(jié)果可以連接,也可以寫入。
阿里云提供的腳本如下:
<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">關(guān)閉壓縮功能</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二進制協(xié)議</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'); //設(shè)置OCS帳號密碼進行鑒權(quán),如已開啟免密碼功能,則無需此步驟</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驅(qū)動,在 /vendor/laravel/framework/src/Illuminate/Cache/MemcachedConnector.php 中創(chuàng)建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沒有設(shè)置setOption方法的選項,僅僅包含最簡連接建立,緊接著就調(diào)用getVersion來測試是否連通。而阿里云的演示代碼是設(shè)置了關(guān)閉壓縮和使用binary二進制協(xié)議的選項的。
沒辦法只能自己來擴展Memcached的功能實現(xiàn)自定義選項。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"> 創(chuàng)建 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"> 創(chuàng)建 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">* * 創(chuàng)建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 服務(wù)器配置</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 類來創(chuàng)建新的 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"> 如果服務(wù)器上的 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>
?
網(wǎng)上有流傳的laravel緩存擴展的文章,其中對配置讀取在5.2以上版本不適用。
緩存擴展后的代碼是需要創(chuàng)建一個ServiceProvider來注冊服務(wù)提供者。服務(wù)提供者是Laravel應(yīng)用啟動的中心,你自己的應(yīng)用以及所有Laravel的核心服務(wù)都是通過服務(wù)提供者啟動。
但是,我們所謂的“啟動”指的是什么?通常,這意味著注冊事物,包括注冊服務(wù)容器綁定、事件監(jiān)聽器、中間件甚至路由。服務(wù)提供者是應(yīng)用配置的中心。
如果你打開Laravel自帶的config/app.php文件,將會看到一個providers數(shù)組,這里就是應(yīng)用所要加載的所有服務(wù)提供者類,當(dāng)然,其中很多是延遲加載的,也就是說不是每次請求都會被加載,只有真的用到它們的時候才會加載。
所有的服務(wù)提供者都繼承自Illuminate\Support\ServiceProvider類。大部分服務(wù)提供者都包含兩個方法: register 和 boot 。在register方法中,你唯一要做的事情就是綁事物到服務(wù)容器,不要嘗試在其中注冊事件監(jiān)聽器,路由或者任何其它功能。
通過Artisan命令make:provider可以簡單生成一個新的提供者:
php artisan <span style="color: #0000ff">make</span>:provider MemcachedExtendServiceProvider
所有服務(wù)提供者都是通過配置文件config/app.php中進行注冊,該文件包含了一個列出所有服務(wù)提供者名字的providers數(shù)組,默認情況下,其中列出了所有核心服務(wù)提供者,這些服務(wù)提供者啟動Laravel核心組件,比如郵件、隊列、緩存等等。
要注冊你自己的服務(wù)提供者,只需要將其追加到該數(shù)組中即可:
<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節(jié)點添加實現(xiàn)的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也儲存到我們擴展的緩存中還需要調(diào)用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"> 創(chuàng)建 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"> 創(chuàng)建 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">* * 創(chuàng)建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 服務(wù)器配置</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 類來創(chuàng)建新的 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"> 如果服務(wù)器上的 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官網(wǎng): https://www.iminho.me
SmartWiki源碼:?https://github.com/lifei6671/SmartWiki
?

熱AI工具

Undress AI Tool
免費脫衣服圖片

Undresser.AI Undress
人工智能驅(qū)動的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover
用于從照片中去除衣服的在線人工智能工具。

Clothoff.io
AI脫衣機

Video Face Swap
使用我們完全免費的人工智能換臉工具輕松在任何視頻中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的代碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
功能強大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級代碼編輯軟件(SublimeText3)