Home > php教程 > PHP开发 > body text

SmartWiki develops Laravel caching extension

高洛峰
Release: 2016-12-02 16:39:51
Original
1127 people have browsed it

Because the SmartWiki demo site is deployed on Alibaba Cloud, Alibaba Cloud has a 128M free Memcache service. After configuring it according to the Memcached configuration method, I found that Laravel reported an error. Check the log and the error location is addServer error and cannot connect to Alibaba Cloud. Memcache.

I was helpless, so I wrote a script according to the Alibaba Cloud installation manual and put it on the server. As a result, I could connect and write.

The script provided by Alibaba Cloud is as follows:

<?php
$connect = new Memcached;  //声明一个新的memcached链接
$connect->setOption(Memcached::OPT_COMPRESSION, false); //关闭压缩功能
$connect->setOption(Memcached::OPT_BINARY_PROTOCOL, true); //使用binary二进制协议
$connect->addServer(&#39;00000000.ocs.aliyuncs.com&#39;, 11211); //添加OCS实例地址及端口号
//$connect->setSaslAuthData(&#39;aaaaaaaaaa, &#39;password&#39;); //设置OCS帐号密码进行鉴权,如已开启免密码功能,则无需此步骤
$connect->set("hello", "world");
echo &#39;hello: &#39;,$connect->get("hello");
print_r( $connect->getVersion());
$connect->quit();
Copy after login

Look at laravel's Memcached driver. The code to create the Memcached object in /vendor/laravel/framework/src/Illuminate/Cache/MemcachedConnector.php is as follows:

public function connect(array $servers)
{
    $memcached = $this->getMemcached();
    // For each server in the array, we&#39;ll just extract the configuration and add
    // the server to the Memcached connection. Once we have added all of these
    // servers we&#39;ll verify the connection is successful and return it back.
    foreach ($servers as $server) {
        $memcached->addServer(
            $server[&#39;host&#39;], $server[&#39;port&#39;], $server[&#39;weight&#39;]
        );
    }
    $memcachedStatus = $memcached->getVersion();
    if (! is_array($memcachedStatus)) {
        throw new RuntimeException(&#39;No Memcached servers added.&#39;);
    }
    if (in_array(&#39;255.255.255&#39;, $memcachedStatus) && count(array_unique($memcachedStatus)) === 1) {
        throw new RuntimeException(&#39;Could not establish Memcached connection.&#39;);
    }
    return $memcached;
}
Copy after login

You can see Laravel's Memcached does not set the option of the setOption method. It only involves the simplest connection establishment, and then calls getVersion to test whether it is connected. Alibaba Cloud's demo code sets the options to turn off compression and use the binary binary protocol.

There is no choice but to extend the functions of Memcached yourself to implement custom options. The extended cache in laravel can be extended using Cache::extend. The extension code is as follows:

Cache::extend(&#39;MemcachedExtend&#39;, function ($app) {

    $memcached = $this->createMemcached($app);

    // 从配置文件中读取缓存前缀
    $prefix = $app[&#39;config&#39;][&#39;cache.prefix&#39;];

    // 创建 MemcachedStore 对象
    $store = new MemcachedStore($memcached, $prefix);

    // 创建 Repository 对象,并返回
    return new Repository($store);
});
Copy after login
/**
 * 创建Memcached对象
 * @param $app
 * @return mixed
 */
protected function createMemcached($app)
{
    // 从配置文件中读取 Memcached 服务器配置
    $servers = $app[&#39;config&#39;][&#39;cache.stores.MemcachedExtend.servers&#39;];


    // 利用 Illuminate\Cache\MemcachedConnector 类来创建新的 Memcached 对象
    $memcached = new \Memcached;

    foreach ($servers as $server) {
        $memcached->addServer(
            $server[&#39;host&#39;], $server[&#39;port&#39;], $server[&#39;weight&#39;]
        );
    }

    // 如果服务器上的 PHP Memcached 扩展支持 SASL 认证
    if (ini_get(&#39;memcached.use_sasl&#39;) && isset($app[&#39;config&#39;][&#39;cache.storess.MemcachedExtend.memcached_user&#39;]) && isset($app[&#39;config&#39;][&#39;cache.storess.MemcachedExtend.memcached_pass&#39;])) {

        // 从配置文件中读取 sasl 认证用户名
        $user = $app[&#39;config&#39;][&#39;cache.storess.MemcachedExtend.memcached_user&#39;];

        // 从配置文件中读取 sasl 认证密码
        $pass = $app[&#39;config&#39;][&#39;cache.storess.MemcachedExtend.memcached_pass&#39;];

        // 指定用于 sasl 认证的账号密码
        $memcached->setSaslAuthData($user, $pass);
    }

    //扩展
    if (isset($app[&#39;config&#39;][&#39;cache.stores.MemcachedExtend.options&#39;])) {
        foreach ($app[&#39;config&#39;][&#39;cache.stores.MemcachedExtend.options&#39;] as $key => $option) {
            $memcached->setOption($key, $option);
        }
    }
    $memcachedStatus = $memcached->getVersion();

    if (! is_array($memcachedStatus)) {
        throw new RuntimeException(&#39;No Memcached servers added.&#39;);
    }

    if (in_array(&#39;255.255.255&#39;, $memcachedStatus) && count(array_unique($memcachedStatus)) === 1) {
        throw new RuntimeException(&#39;Could not establish Memcached connection.&#39;);
    }

    return $memcached;
}
Copy after login

The cache extension code requires creating a ServiceProvider to register the service provider. The service provider is the center of Laravel application startup. Your own application and all Laravel's core services are started through the service provider.

But what do we mean by “startup”? Typically, this means registering things, including registering service container bindings, event listeners, middleware, and even routes. Service providers are the center of application configuration.

If you open the config/app.php file that comes with Laravel, you will see a providers array. Here are all the service provider classes to be loaded by the application. Of course, many of them are lazy loaded, which means that they are not loaded every time. They will be loaded every request, and will only be loaded when they are actually used.

All service providers inherit from the IlluminateSupportServiceProvider class. Most service providers contain two methods: register and boot . In the register method, the only thing you have to do is bind the thing to the service container. Do not try to register event listeners, routes or any other functionality in it.

You can simply generate a new provider through the Artisan command make:provider:

php artisan make:provider MemcachedExtendServiceProvider

All service providers are registered through the configuration file config/app.php, which contains A providers array listing the names of all service providers. By default, all core service providers are listed. These service providers enable core Laravel components such as mail, queues, caches, etc.

To register your own service provider, just append it to the array:

&#39;providers&#39; => [
    SmartWiki\Providers\MemcachedExtendServiceProvider::class //
    在providers节点添加实现的provider
    ]
Copy after login

Also configure the Memcached configuration in config/cache.php:

&#39;MemcachedExtend&#39; => [
    &#39;driver&#39; => &#39;MemcachedExtend&#39;,
    &#39;servers&#39; => [
        [
            &#39;host&#39; => env(&#39;MEMCACHED_EXTEND_HOST&#39;, &#39;127.0.0.1&#39;),
            &#39;port&#39; => env(&#39;MEMCACHED_EXTEND_PORT&#39;, 11211),
            &#39;weight&#39; => 100,
        ],
    ],
    &#39;options&#39; => [
        \Memcached::OPT_BINARY_PROTOCOL => true,
        \Memcached::OPT_COMPRESSION => false
    ]
]
Copy after login

If you need to also store the Session in our extension We also need to call Session::extend in the cache to expand our Session storage:

Session::extend(&#39;MemcachedExtend&#39;,function ($app){    
$memcached = $this->createMemcached($app);   
 return new MemcachedSessionHandler($memcached);
});
Copy after login

Then we can configure our extended cache in .env. The complete code is as follows:

<?php

namespace SmartWiki\Providers;

use Illuminate\Cache\Repository;
use Illuminate\Cache\MemcachedStore;
use Illuminate\Support\ServiceProvider;

use Cache;
use Session;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler;
use RuntimeException;

class MemcachedExtendServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {

        Cache::extend(&#39;MemcachedExtend&#39;, function ($app) {

            $memcached = $this->createMemcached($app);

            // 从配置文件中读取缓存前缀
            $prefix = $app[&#39;config&#39;][&#39;cache.prefix&#39;];

            // 创建 MemcachedStore 对象
            $store = new MemcachedStore($memcached, $prefix);

            // 创建 Repository 对象,并返回
            return new Repository($store);
        });

        Session::extend(&#39;MemcachedExtend&#39;,function ($app){
            $memcached = $this->createMemcached($app);


            return new MemcachedSessionHandler($memcached);
        });
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * 创建Memcached对象
     * @param $app
     * @return mixed
     */
    protected function createMemcached($app)
    {
        // 从配置文件中读取 Memcached 服务器配置
        $servers = $app[&#39;config&#39;][&#39;cache.stores.MemcachedExtend.servers&#39;];


        // 利用 Illuminate\Cache\MemcachedConnector 类来创建新的 Memcached 对象
        $memcached = new \Memcached;

        foreach ($servers as $server) {
            $memcached->addServer(
                $server[&#39;host&#39;], $server[&#39;port&#39;], $server[&#39;weight&#39;]
            );
        }

        // 如果服务器上的 PHP Memcached 扩展支持 SASL 认证
        if (ini_get(&#39;memcached.use_sasl&#39;) && isset($app[&#39;config&#39;][&#39;cache.storess.MemcachedExtend.memcached_user&#39;]) && isset($app[&#39;config&#39;][&#39;cache.storess.MemcachedExtend.memcached_pass&#39;])) {

            // 从配置文件中读取 sasl 认证用户名
            $user = $app[&#39;config&#39;][&#39;cache.storess.MemcachedExtend.memcached_user&#39;];

            // 从配置文件中读取 sasl 认证密码
            $pass = $app[&#39;config&#39;][&#39;cache.storess.MemcachedExtend.memcached_pass&#39;];

            // 指定用于 sasl 认证的账号密码
            $memcached->setSaslAuthData($user, $pass);
        }

        //扩展
        if (isset($app[&#39;config&#39;][&#39;cache.stores.MemcachedExtend.options&#39;])) {
            foreach ($app[&#39;config&#39;][&#39;cache.stores.MemcachedExtend.options&#39;] as $key => $option) {
                $memcached->setOption($key, $option);
            }
        }
        $memcachedStatus = $memcached->getVersion();

        if (! is_array($memcachedStatus)) {
            throw new RuntimeException(&#39;No Memcached servers added.&#39;);
        }

        if (in_array(&#39;255.255.255&#39;, $memcachedStatus) && count(array_unique($memcachedStatus)) === 1) {
            throw new RuntimeException(&#39;Could not establish Memcached connection.&#39;);
        }

        return $memcached;
    }
}

SmartWikiCode
Copy after login


Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Recommendations
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template