Issues (1474)

framework/Caching/TRedisCache.php (2 issues)

1
<?php
2
3
/**
4
 * TRedisCache class file
5
 *
6
 * @author Jens Klaer <[email protected]>
7
 * @author LANDWEHR Computer und Software GmbH
8
 * @link https://github.com/pradosoft/prado4
9
 * @license https://github.com/pradosoft/prado4/blob/master/LICENSE
10
 */
11
12
namespace Prado\Caching;
13
14
use Prado\Exceptions\TConfigurationException;
15
use Prado\Exceptions\TInvalidOperationException;
16
use Prado\Prado;
17
use Prado\TPropertyValue;
18
use Prado\Xml\TXmlElement;
19
20
/**
21
 * TRedisCache class
22
 *
23
 * TRedisCache implements a cache application module based on {@see https://redis.io/ redis} key-value store.
24
 *
25
 * TRedisCache can be configured with the {@see setHost Host} and {@see setPort Port}
26
 * properties, which specify the host and port of the redis server to be used.
27
 * By default, they take the value 'localhost' and 6379, respectively.
28
 *
29
 * It is also possible to use a unix socket for connection, it can be set
30
 * using {@see setSocket}. Be sure that the socket is readable/writeable by
31
 * the webserver/php user. By default, this value is left empty. If both,
32
 * server/port and socket are set, the latter takes precedence.
33
 *
34
 * Use the {@see setIndex Index} property to change the database to the given
35
 * database index. Defaults to 0.
36
 *
37
 * The following basic cache operations are implemented:
38
 * - {@see get} : retrieve the value with a key (if any) from cache
39
 * - {@see set} : store the value with a key into cache
40
 * - {@see add} : store the value only if cache does not have this key
41
 * - {@see delete} : delete the value with the specified key from cache
42
 * - {@see flush} : delete all values from cache
43
 *
44
 * Each value is associated with an expiration time. The {@see get} operation
45
 * ensures that any expired value will not be returned. The expiration time can
46
 * be specified by the number of seconds. A expiration time 0 represents never expire.
47
 *
48
 * By definition, cache does not ensure the existence of a value
49
 * even if it never expires. Cache is not meant to be an persistent storage.
50
 *
51
 * Also note, there is no security measure to protected data in redis cache.
52
 * All data in redis cache can be accessed by any process running in the system.
53
 *
54
 * To use this module, the php-redis extension must be loaded.
55
 *
56
 * Some usage examples of TRedisCache are as follows,
57
 * ```php
58
 * $cache=new TRedisCache;  // TRedisache may also be loaded as a Prado application module
59
 * $cache->init(null);
60
 * $cache->add('object',$object);
61
 * $object2=$cache->get('object');
62
 * ```
63
 *
64
 * If loaded as module, TRedisCache will register itself with {@see \Prado\TApplication} as the
65
 * default cache module. It can be accessed via {@see \Prado\TApplication::getCache()}.
66
 *
67
 * TRedisCache may be configured in application configuration file as follows
68
 * ```php
69
 * <module id="cache" class="Prado\Caching\TRedisCache" Host="localhost" Port="6379" />
70
 * ```
71
 * or
72
 * ```php
73
 * <module id="cache" class="Prado\Caching\TRedisCache" Socket="var/run/redis/redis.sock" Index="2" />
74
 * ```
75
 * where {@see setHost Host} and {@see setPort Port} or {@see setSocket Socket} are configurable properties
76
 * of TRedisCache.
77
 *
78
 * @author Jens Klaer <[email protected]>
79
 * @author LANDWEHR Computer und Software GmbH
80
 * @since 4.0
81
 */
82
class TRedisCache extends TCache
83
{
84
	/**
85
	 * @var bool if the module is initialized
86
	 */
87
	private $_initialized = false;
88
	/**
89
	 * @var \Redis the Redis instance
90
	 */
91
	private $_cache;
92
	/**
93
	 * @var string host name of the redis cache server
94
	 */
95
	private $_host = 'localhost';
96
	/**
97
	 * @var int the port number of the redis cache server
98
	 */
99
	private $_port = 6379;
100
	/**
101
	 * @var string the unix socket of the redis cache server.
102
	 */
103
	private $_socket;
104
	/**
105
	 * @var int the database index to use within the redis server.
106
	 */
107
	private $_index = 0;
108
109
	/**
110
	 * Destructor.
111
	 * Disconnect the redis cache server.
112
	 */
113
	public function __destruct()
114
	{
115
		if ($this->_cache instanceof \Redis) {
0 ignored issues
show
$this->_cache is always a sub-type of Redis.
Loading history...
116
			$this->_cache->close();
117
		}
118
		parent::__destruct();
119
	}
120
121
	/**
122
	 * Initializes this module.
123
	 * This method is required by the IModule interface. It creates a Redis instance and connects to the redis server.
124
	 * @param \Prado\Xml\TXmlElement $config configuration for this module, can be null
125
	 * @throws TConfigurationException if php-redis extension is not installed or redis cache sever connection fails
126
	 */
127
	public function init($config)
128
	{
129
		if (!extension_loaded('redis') || !class_exists('\Redis', false)) {
130
			throw new TConfigurationException('rediscache_extension_required');
131
		}
132
		$this->_cache = new \Redis();
133
		if ($this->_socket !== null) {
134
			$this->_cache->connect($this->_socket);
135
		} else {
136
			$this->_cache->connect($this->_host, $this->_port);
137
		}
138
		$this->_cache->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP);
139
		$this->_cache->select($this->_index);
140
		parent::init($config);
141
		$this->_initialized = true;
142
	}
143
144
	/**
145
	 * @param mixed $key
146
	 * @return bool always true
147
	 */
148
	public function valid($key)
0 ignored issues
show
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

148
	public function valid(/** @scrutinizer ignore-unused */ $key)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
149
	{
150
		return true;
151
	}
152
153
	/**
154
	 * @return string the host name of the redis cache server
155
	 */
156
	public function getHost()
157
	{
158
		return $this->_host;
159
	}
160
161
	/**
162
	 * @param string $value the host name of the redis cache server
163
	 * @throws TInvalidOperationException if the module is already initialized
164
	 */
165
	public function setHost($value)
166
	{
167
		if ($this->_initialized) {
168
			throw new TInvalidOperationException('rediscache_host_unchangeable');
169
		} else {
170
			$this->_host = $value;
171
		}
172
	}
173
174
	/**
175
	 * @return int the port number of the redis cache server
176
	 */
177
	public function getPort()
178
	{
179
		return $this->_port;
180
	}
181
182
	/**
183
	 * @param int $value the port number of the redis cache server
184
	 * @throws TInvalidOperationException if the module is already initialized
185
	 */
186
	public function setPort($value)
187
	{
188
		if ($this->_initialized) {
189
			throw new TInvalidOperationException('rediscache_port_unchangeable');
190
		} else {
191
			$this->_port = TPropertyValue::ensureInteger($value);
192
		}
193
	}
194
195
	/**
196
	 * @return string the unix socket of the redis cache server
197
	 */
198
	public function getSocket()
199
	{
200
		return $this->_socket;
201
	}
202
203
	/**
204
	 * @param string $value the unix socket of the redis cache server
205
	 * @throws TInvalidOperationException if the module is already initialized
206
	 */
207
	public function setSocket($value)
208
	{
209
		if ($this->_initialized) {
210
			throw new TInvalidOperationException('rediscache_socket_unchangeable');
211
		} else {
212
			$this->_socket = TPropertyValue::ensureString($value);
213
		}
214
	}
215
216
	/**
217
	 * @return int the database index to use. Defaults to 0.
218
	 */
219
	public function getIndex()
220
	{
221
		return $this->_index;
222
	}
223
224
	/**
225
	 * @param int $value the database index to use.
226
	 * @throws TInvalidOperationException if the module is already initialized
227
	 */
228
	public function setIndex($value)
229
	{
230
		if ($this->_initialized) {
231
			throw new TInvalidOperationException('rediscache_index_unchangeable');
232
		} else {
233
			$this->_index = TPropertyValue::ensureInteger($value);
234
		}
235
	}
236
237
	/**
238
	 * Retrieves a value from cache with a specified key.
239
	 * This is the implementation of the method declared in the parent class.
240
	 * @param string $key a unique key identifying the cached value
241
	 * @return false|string the value stored in cache, false if the value is not in the cache or expired.
242
	 */
243
	protected function getValue($key)
244
	{
245
		return $this->_cache->get($key);
246
	}
247
248
	/**
249
	 * Stores a value identified by a key in cache.
250
	 * This is the implementation of the method declared in the parent class.
251
	 *
252
	 * @param string $key the key identifying the value to be cached
253
	 * @param string $value the value to be cached
254
	 * @param int $expire the number of seconds in which the cached value will expire. 0 means never expire.
255
	 * @return bool true if the value is successfully stored into cache, false otherwise
256
	 */
257
	protected function setValue($key, $value, $expire)
258
	{
259
		$options = $expire === 0 ? [] : ['ex' => $expire];
260
		return $this->_cache->set($key, $value, $options);
261
	}
262
263
	/**
264
	 * Stores a value identified by a key into cache if the cache does not contain this key.
265
	 * This is the implementation of the method declared in the parent class.
266
	 *
267
	 * @param string $key the key identifying the value to be cached
268
	 * @param string $value the value to be cached
269
	 * @param int $expire the number of seconds in which the cached value will expire. 0 means never expire.
270
	 * @return bool true if the value is successfully stored into cache, false otherwise
271
	 */
272
	protected function addValue($key, $value, $expire)
273
	{
274
		$options = $expire === 0 ? ['nx'] : ['nx', 'ex' => $expire];
275
		return $this->_cache->set($key, $value, $options);
276
	}
277
278
	/**
279
	 * Deletes a value with the specified key from cache
280
	 * This is the implementation of the method declared in the parent class.
281
	 * @param string $key the key of the value to be deleted
282
	 * @return bool if no error happens during deletion
283
	 */
284
	protected function deleteValue($key)
285
	{
286
		$this->_cache->delete($key);
287
		return true;
288
	}
289
290
	/**
291
	 * Deletes all values from cache, only clearing the currently selected database.
292
	 * @return bool if no error happens during flush
293
	 */
294
	public function flush()
295
	{
296
		return $this->_cache->flushDB();
297
	}
298
}
299