Completed
Push — update-to-php-71 ( add189...8e7ebf )
by Alexander
04:33
created

MemCached::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\caching;
9
10
use Yii;
11
use yii\base\InvalidConfigException;
12
13
/**
14
 * MemCached implements a cache application component based on [memcached](http://pecl.php.net/package/memcached) PECL
15
 * extension.
16
 *
17
 * MemCached can be configured with a list of memcached servers by settings its [[servers]] property.
18
 * By default, MemCached assumes there is a memcached server running on localhost at port 11211.
19
 *
20
 * See [[Cache]] for common cache operations that MemCached supports.
21
 *
22
 * Note, there is no security measure to protected data in memcached.
23
 * All data in memcached can be accessed by any process running in the system.
24
 *
25
 * To use MemCached as the cache application component, configure the application as follows,
26
 *
27
 * ```php
28
 * [
29
 *     'components' => [
30
 *         'cache' => [
31
 *             'class' => \yii\caching\MemCached::class,
32
 *             'servers' => [
33
 *                 [
34
 *                     'host' => 'server1',
35
 *                     'port' => 11211,
36
 *                     'weight' => 60,
37
 *                 ],
38
 *                 [
39
 *                     'host' => 'server2',
40
 *                     'port' => 11211,
41
 *                     'weight' => 40,
42
 *                 ],
43
 *             ],
44
 *         ],
45
 *     ],
46
 * ]
47
 * ```
48
 *
49
 * In the above, two memcached servers are used: server1 and server2. You can configure more properties of
50
 * each server, such as `persistent`, `weight`, `timeout`. Please see [[MemCacheServer]] for available options.
51
 *
52
 * For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview).
53
 *
54
 * @property \Memcached $memcached The memcached object used by this cache component.
55
 * This property is read-only.
56
 * @property MemCachedServer[] $servers List of memcached server configurations. Note that the type of this
57
 * property differs in getter and setter. See [[getServers()]] and [[setServers()]] for details.
58
 *
59
 * @author Qiang Xue <[email protected]>
60
 * @since 2.0
61
 */
62
class MemCached extends Cache
63
{
64
    /**
65
     * @var string an ID that identifies a Memcached instance.
66
     * By default the Memcached instances are destroyed at the end of the request. To create an instance that
67
     * persists between requests, you may specify a unique ID for the instance. All instances created with the
68
     * same ID will share the same connection.
69
     * @see http://ca2.php.net/manual/en/memcached.construct.php
70
     */
71
    public $persistentId;
72
    /**
73
     * @var array options for Memcached.
74
     * @see http://ca2.php.net/manual/en/memcached.setoptions.php
75
     */
76
    public $options;
77
    /**
78
     * @var string memcached sasl username.
79
     * @see http://php.net/manual/en/memcached.setsaslauthdata.php
80
     */
81
    public $username;
82
    /**
83
     * @var string memcached sasl password.
84
     * @see http://php.net/manual/en/memcached.setsaslauthdata.php
85
     */
86
    public $password;
87
88
    /**
89
     * @var \Memcached the Memcached instance
90
     */
91
    private $_cache;
92
    /**
93
     * @var array list of memcached server configurations
94
     */
95
    private $_servers = [];
96
97
98
    /**
99
     * Initializes this application component.
100
     * It creates the memcached instance and adds memcached servers.
101
     */
102
    public function init()
103
    {
104
        parent::init();
105
        $this->addServers($this->getMemcached(), $this->getServers());
106
    }
107
108
    /**
109
     * Add servers to the server pool of the cache specified
110
     *
111
     * @param \Memcached $cache
112
     * @param MemCachedServer[] $servers
113
     * @throws InvalidConfigException
114
     */
115
    protected function addServers($cache, $servers)
116
    {
117
        if (empty($servers)) {
118
            $servers = [new MemCachedServer([
119
                'host' => '127.0.0.1',
120
                'port' => 11211,
121
            ])];
122
        } else {
123
            foreach ($servers as $server) {
124
                if ($server->host === null) {
125
                    throw new InvalidConfigException("The 'host' property must be specified for every memcached server.");
126
                }
127
            }
128
        }
129
130
        $existingServers = [];
131
        if ($this->persistentId !== null) {
132
            foreach ($cache->getServerList() as $s) {
133
                $existingServers[$s['host'] . ':' . $s['port']] = true;
134
            }
135
        }
136
        foreach ($servers as $server) {
137
            if (empty($existingServers) || !isset($existingServers[$server->host . ':' . $server->port])) {
138
                $cache->addServer($server->host, $server->port, $server->weight);
139
            }
140
        }
141
    }
142
143
    /**
144
     * Returns the underlying memcached object.
145
     * @return \Memcached the memcached object used by this cache component.
146
     * @throws InvalidConfigException if memcached extension is not loaded
147
     */
148
    public function getMemcached()
149
    {
150
        if ($this->_cache === null) {
151
            if (!extension_loaded('memcached')) {
152
                throw new InvalidConfigException('MemCached requires PHP memcached extension to be loaded.');
153
            }
154
155
            $this->_cache = $this->persistentId !== null ? new \Memcached($this->persistentId) : new \Memcached;
156
            if ($this->username !== null || $this->password !== null) {
157
                $this->_cache->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);
158
                $this->_cache->setSaslAuthData($this->username, $this->password);
159
            }
160
            if (!empty($this->options)) {
161
                $this->_cache->setOptions($this->options);
0 ignored issues
show
Bug introduced by
The method setOptions() does not exist on Memcached. Did you maybe mean setOption()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
162
            }
163
        }
164
165
        return $this->_cache;
166
    }
167
168
    /**
169
     * Returns the memcached server configurations.
170
     * @return MemCachedServer[] list of memcached server configurations.
171
     */
172
    public function getServers()
173
    {
174
        return $this->_servers;
175
    }
176
177
    /**
178
     * @param array $config list of memcached server configurations. Each element must be an array
179
     * with the following keys: host, port, persistent, weight, timeout, retryInterval, status.
180
     * @see http://php.net/manual/en/memcached.addserver.php
181
     */
182
    public function setServers($config)
183
    {
184
        foreach ($config as $c) {
185
            $this->_servers[] = new MemCachedServer($c);
186
        }
187
    }
188
189
    /**
190
     * Retrieves a value from cache with a specified key.
191
     * This is the implementation of the method declared in the parent class.
192
     * @param string $key a unique key identifying the cached value
193
     * @return mixed|false the value stored in cache, false if the value is not in the cache or expired.
194
     */
195
    protected function getValue($key)
196
    {
197
        return $this->_cache->get($key);
198
    }
199
200
    /**
201
     * Retrieves multiple values from cache with the specified keys.
202
     * @param array $keys a list of keys identifying the cached values
203
     * @return array a list of cached values indexed by the keys
204
     */
205
    protected function getValues($keys)
206
    {
207
        return $this->_cache->getMulti($keys);
208
    }
209
210
    /**
211
     * Stores a value identified by a key in cache.
212
     * This is the implementation of the method declared in the parent class.
213
     *
214
     * @param string $key the key identifying the value to be cached
215
     * @param mixed $value the value to be cached.
216
     * @see [Memcached::set()](http://php.net/manual/en/memcached.set.php)
217
     * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire.
218
     * @return bool true if the value is successfully stored into cache, false otherwise
219
     */
220
    protected function setValue($key, $value, $duration)
221
    {
222
        // Use UNIX timestamp since it doesn't have any limitation
223
        // @see http://php.net/manual/en/memcached.expiration.php
224
        $expire = $duration > 0 ? $duration + time() : 0;
225
226
        return $this->_cache->set($key, $value, $expire);
227
    }
228
229
    /**
230
     * Stores multiple key-value pairs in cache.
231
     * @param array $data array where key corresponds to cache key while value is the value stored
232
     * @param int $duration the number of seconds in which the cached values will expire. 0 means never expire.
233
     * @return array array of failed keys.
234
     */
235
    protected function setValues($data, $duration)
236
    {
237
        // Use UNIX timestamp since it doesn't have any limitation
238
        // @see http://php.net/manual/en/memcached.expiration.php
239
        $expire = $duration > 0 ? $duration + time() : 0;
240
241
        // Memcached::setMulti() returns boolean
242
        // @see http://php.net/manual/en/memcached.setmulti.php
243
        return $this->_cache->setMulti($data, $expire) ? [] : array_keys($data);
244
    }
245
246
    /**
247
     * Stores a value identified by a key into cache if the cache does not contain this key.
248
     * This is the implementation of the method declared in the parent class.
249
     *
250
     * @param string $key the key identifying the value to be cached
251
     * @param mixed $value the value to be cached
252
     * @see [Memcached::set()](http://php.net/manual/en/memcached.set.php)
253
     * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire.
254
     * @return bool true if the value is successfully stored into cache, false otherwise
255
     */
256
    protected function addValue($key, $value, $duration)
257
    {
258
        // Use UNIX timestamp since it doesn't have any limitation
259
        // @see http://php.net/manual/en/memcached.expiration.php
260
        $expire = $duration > 0 ? $duration + time() : 0;
261
262
        return $this->_cache->add($key, $value, $expire);
263
    }
264
265
    /**
266
     * Deletes a value with the specified key from cache
267
     * This is the implementation of the method declared in the parent class.
268
     * @param string $key the key of the value to be deleted
269
     * @return bool if no error happens during deletion
270
     */
271
    protected function deleteValue($key)
272
    {
273
        return $this->_cache->delete($key, 0);
274
    }
275
276
    /**
277
     * Deletes all values from cache.
278
     * This is the implementation of the method declared in the parent class.
279
     * @return bool whether the flush operation was successful.
280
     */
281
    protected function flushValues()
282
    {
283
        return $this->_cache->flush();
284
    }
285
}
286