Issues (9)

src/Connection.php (5 issues)

1
<?php
2
3
/**
4
 * @author: jiangyi
5
 * @date: 下午8:39 2018/12/13
6
 *
7
 * @see https://github.com/yiisoft/yii2-redis/blob/master/src/Connection.php
8
 */
9
10
namespace EasyRedis;
11
12
use EasyRedis\Exceptions\RedisException;
13
use EasyRedis\Exceptions\SocketRedisException;
14
use EasyRedis\Helpers\Inflector;
15
16
/**
17
 * The redis connection class is used to establish a connection to a [redis](http://redis.io/) server.
18
 *
19
 * By default it assumes there is a redis server running on localhost at port 6379 and uses the database number 0.
20
 *
21
 * It is possible to connect to a redis server using [[hostname]] and [[port]] or using a [[unixSocket]].
22
 *
23
 * It also supports [the AUTH command](http://redis.io/commands/auth) of redis.
24
 * When the server needs authentication, you can set the [[password]] property to
25
 * authenticate with the server after connect.
26
 *
27
 * The execution of [redis commands](http://redis.io/commands) is possible with via [[executeCommand()]].
28
 *
29
 * @method mixed append($key, $value) Append a value to a key. <https://redis.io/commands/append>
30
 * @method mixed auth($password) Authenticate to the server. <https://redis.io/commands/auth>
31
 * @method mixed bgrewriteaof() Asynchronously rewrite the append-only file. <https://redis.io/commands/bgrewriteaof>
32
 * @method mixed bgsave() Asynchronously save the dataset to disk. <https://redis.io/commands/bgsave>
33
 * @method mixed bitcount($key, $start = null, $end = null) Count set bits in a string. <https://redis.io/commands/bitcount>
34
 * @method mixed bitfield($key, ...$operations) Perform arbitrary bitfield integer operations on strings. <https://redis.io/commands/bitfield>
35
 * @method mixed bitop($operation, $destkey, ...$keys) Perform bitwise operations between strings. <https://redis.io/commands/bitop>
36
 * @method mixed bitop_a($operation, $destkey, array $keys) Perform bitwise operations between strings. <https://redis.io/commands/bitop>
37
 * @method mixed bitpos($key, $bit, $start = null, $end = null) Find first bit set or clear in a string. <https://redis.io/commands/bitpos>
38
 * @method mixed blpop(...$keys, $timeout) Remove and get the first element in a list, or block until one is available. <https://redis.io/commands/blpop>
39
 * @method mixed blpop_a(array $keys, $timeout) Remove and get the first element in a list, or block until one is available. <https://redis.io/commands/blpop>
40
 * @method mixed brpop(...$keys, $timeout) Remove and get the last element in a list, or block until one is available. <https://redis.io/commands/brpop>
41
 * @method mixed brpop_a(array $keys, $timeout) Remove and get the last element in a list, or block until one is available. <https://redis.io/commands/brpop>
42
 * @method mixed brpoplpush($source, $destination, $timeout) Pop a value from a list, push it to another list and return it; or block until one is available. <https://redis.io/commands/brpoplpush>
43
 * @method mixed clientKill(...$filters) Kill the connection of a client. <https://redis.io/commands/client-kill>
44
 * @method mixed clientList() Get the list of client connections. <https://redis.io/commands/client-list>
45
 * @method mixed clientGetname() Get the current connection name. <https://redis.io/commands/client-getname>
46
 * @method mixed clientPause($timeout) Stop processing commands from clients for some time. <https://redis.io/commands/client-pause>
47
 * @method mixed clientReply($option) Instruct the server whether to reply to commands. <https://redis.io/commands/client-reply>
48
 * @method mixed clientSetname($connectionName) Set the current connection name. <https://redis.io/commands/client-setname>
49
 * @method mixed clusterAddslots(...$slots) Assign new hash slots to receiving node. <https://redis.io/commands/cluster-addslots>
50
 * @method mixed clusterCountkeysinslot($slot) Return the number of local keys in the specified hash slot. <https://redis.io/commands/cluster-countkeysinslot>
51
 * @method mixed clusterDelslots(...$slots) Set hash slots as unbound in receiving node. <https://redis.io/commands/cluster-delslots>
52
 * @method mixed clusterFailover($option = null) Forces a slave to perform a manual failover of its master.. <https://redis.io/commands/cluster-failover>
53
 * @method mixed clusterForget($nodeId) Remove a node from the nodes table. <https://redis.io/commands/cluster-forget>
54
 * @method mixed clusterGetkeysinslot($slot, $count) Return local key names in the specified hash slot. <https://redis.io/commands/cluster-getkeysinslot>
55
 * @method mixed clusterInfo() Provides info about Redis Cluster node state. <https://redis.io/commands/cluster-info>
56
 * @method mixed clusterKeyslot($key) Returns the hash slot of the specified key. <https://redis.io/commands/cluster-keyslot>
57
 * @method mixed clusterMeet($ip, $port) Force a node cluster to handshake with another node. <https://redis.io/commands/cluster-meet>
58
 * @method mixed clusterNodes() Get Cluster config for the node. <https://redis.io/commands/cluster-nodes>
59
 * @method mixed clusterReplicate($nodeId) Reconfigure a node as a slave of the specified master node. <https://redis.io/commands/cluster-replicate>
60
 * @method mixed clusterReset($resetType = "SOFT") Reset a Redis Cluster node. <https://redis.io/commands/cluster-reset>
61
 * @method mixed clusterSaveconfig() Forces the node to save cluster state on disk. <https://redis.io/commands/cluster-saveconfig>
62
 * @method mixed clusterSetslot($slot, $type, $nodeid = null) Bind a hash slot to a specific node. <https://redis.io/commands/cluster-setslot>
63
 * @method mixed clusterSlaves($nodeId) List slave nodes of the specified master node. <https://redis.io/commands/cluster-slaves>
64
 * @method mixed clusterSlots() Get array of Cluster slot to node mappings. <https://redis.io/commands/cluster-slots>
65
 * @method mixed command() Get array of Redis command details. <https://redis.io/commands/command>
66
 * @method mixed commandCount() Get total number of Redis commands. <https://redis.io/commands/command-count>
67
 * @method mixed commandGetkeys() Extract keys given a full Redis command. <https://redis.io/commands/command-getkeys>
68
 * @method mixed commandInfo(...$commandNames) Get array of specific Redis command details. <https://redis.io/commands/command-info>
69
 * @method mixed configGet($parameter) Get the value of a configuration parameter. <https://redis.io/commands/config-get>
70
 * @method mixed configRewrite() Rewrite the configuration file with the in memory configuration. <https://redis.io/commands/config-rewrite>
71
 * @method mixed configSet($parameter, $value) Set a configuration parameter to the given value. <https://redis.io/commands/config-set>
72
 * @method mixed configResetstat() Reset the stats returned by INFO. <https://redis.io/commands/config-resetstat>
73
 * @method mixed dbsize() Return the number of keys in the selected database. <https://redis.io/commands/dbsize>
74
 * @method mixed debugObject($key) Get debugging information about a key. <https://redis.io/commands/debug-object>
75
 * @method mixed debugSegfault() Make the server crash. <https://redis.io/commands/debug-segfault>
76
 * @method mixed decr($key) Decrement the integer value of a key by one. <https://redis.io/commands/decr>
77
 * @method mixed decrby($key, $decrement) Decrement the integer value of a key by the given number. <https://redis.io/commands/decrby>
78
 * @method mixed del(...$keys) Delete a key. <https://redis.io/commands/del>
79
 * @method mixed del_a(array $keys) Delete a key. <https://redis.io/commands/del>
80
 * @method mixed discard() Discard all commands issued after MULTI. <https://redis.io/commands/discard>
81
 * @method mixed dump($key) Return a serialized version of the value stored at the specified key.. <https://redis.io/commands/dump>
82
 * @method mixed echo($message) Echo the given string. <https://redis.io/commands/echo>
83
 * @method mixed eval($script, $numkeys, ...$keys, ...$args) Execute a Lua script server side. <https://redis.io/commands/eval>
84
 * @method mixed evalsha($sha1, $numkeys, ...$keys, ...$args) Execute a Lua script server side. <https://redis.io/commands/evalsha>
85
 * @method mixed exec() Execute all commands issued after MULTI. <https://redis.io/commands/exec>
86
 * @method mixed exists(...$keys) Determine if a key exists. <https://redis.io/commands/exists>
87
 * @method mixed exists_a(array $keys) Determine if a key exists. <https://redis.io/commands/exists>
88
 * @method mixed expire($key, $seconds) Set a key's time to live in seconds. <https://redis.io/commands/expire>
89
 * @method mixed expireat($key, $timestamp) Set the expiration for a key as a UNIX timestamp. <https://redis.io/commands/expireat>
90
 * @method mixed flushall($ASYNC = null) Remove all keys from all databases. <https://redis.io/commands/flushall>
91
 * @method mixed flushdb($ASYNC = null) Remove all keys from the current database. <https://redis.io/commands/flushdb>
92
 * @method mixed geoadd($key, $longitude, $latitude, $member, ...$more) Add one or more geospatial items in the geospatial index represented using a sorted set. <https://redis.io/commands/geoadd>
93
 * @method mixed geoadd_a($key, array $data) Add one or more geospatial items in the geospatial index represented using a sorted set. <https://redis.io/commands/geoadd>
94
 * @method mixed geohash($key, ...$members) Returns members of a geospatial index as standard geohash strings. <https://redis.io/commands/geohash>
95
 * @method mixed geopos($key, ...$members) Returns longitude and latitude of members of a geospatial index. <https://redis.io/commands/geopos>
96
 * @method mixed geodist($key, $member1, $member2, $unit = null) Returns the distance between two members of a geospatial index. <https://redis.io/commands/geodist>
97
 * @method mixed georadius($key, $longitude, $latitude, $radius, $metric, ...$options) Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a point. <https://redis.io/commands/georadius>
98
 * @method mixed georadiusbymember($key, $member, $radius, $metric, ...$options) Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a member. <https://redis.io/commands/georadiusbymember>
99
 * @method mixed get($key) Get the value of a key. <https://redis.io/commands/get>
100
 * @method mixed getbit($key, $offset) Returns the bit value at offset in the string value stored at key. <https://redis.io/commands/getbit>
101
 * @method mixed getrange($key, $start, $end) Get a substring of the string stored at a key. <https://redis.io/commands/getrange>
102
 * @method mixed getset($key, $value) Set the string value of a key and return its old value. <https://redis.io/commands/getset>
103
 * @method mixed hdel($key, ...$fields) Delete one or more hash fields. <https://redis.io/commands/hdel>
104
 * @method mixed hdel_a($key, array $fields) Delete one or more hash fields. <https://redis.io/commands/hdel>
105
 * @method mixed hexists($key, $field) Determine if a hash field exists. <https://redis.io/commands/hexists>
106
 * @method mixed hget($key, $field) Get the value of a hash field. <https://redis.io/commands/hget>
107
 * @method mixed hgetall($key) Get all the fields and values in a hash. <https://redis.io/commands/hgetall>
108
 * @method mixed hincrby($key, $field, $increment) Increment the integer value of a hash field by the given number. <https://redis.io/commands/hincrby>
109
 * @method mixed hincrbyfloat($key, $field, $increment) Increment the float value of a hash field by the given amount. <https://redis.io/commands/hincrbyfloat>
110
 * @method mixed hkeys($key) Get all the fields in a hash. <https://redis.io/commands/hkeys>
111
 * @method mixed hlen($key) Get the number of fields in a hash. <https://redis.io/commands/hlen>
112
 * @method mixed hmget($key, ...$fields) Get the values of all the given hash fields. <https://redis.io/commands/hmget>
113
 * @method mixed hmget_a($key, array $fields) Get the values of all the given hash fields. <https://redis.io/commands/hmget>
114
 * @method mixed hmset($key, $field, $value, ...$more) Set multiple hash fields to multiple values. <https://redis.io/commands/hmset>
115
 * @method mixed hmset_a($key, array $fieldValuePairs) Set multiple hash fields to multiple values. <https://redis.io/commands/hmset>
116
 * @method mixed hset($key, $field, $value) Set the string value of a hash field. <https://redis.io/commands/hset>
117
 * @method mixed hsetnx($key, $field, $value) Set the value of a hash field, only if the field does not exist. <https://redis.io/commands/hsetnx>
118
 * @method mixed hstrlen($key, $field) Get the length of the value of a hash field. <https://redis.io/commands/hstrlen>
119
 * @method mixed hvals($key) Get all the values in a hash. <https://redis.io/commands/hvals>
120
 * @method mixed incr($key) Increment the integer value of a key by one. <https://redis.io/commands/incr>
121
 * @method mixed incrby($key, $increment) Increment the integer value of a key by the given amount. <https://redis.io/commands/incrby>
122
 * @method mixed incrbyfloat($key, $increment) Increment the float value of a key by the given amount. <https://redis.io/commands/incrbyfloat>
123
 * @method mixed info($section = null) Get information and statistics about the server. <https://redis.io/commands/info>
124
 * @method mixed keys($pattern) Find all keys matching the given pattern. <https://redis.io/commands/keys>
125
 * @method mixed lastsave() Get the UNIX time stamp of the last successful save to disk. <https://redis.io/commands/lastsave>
126
 * @method mixed lindex($key, $index) Get an element from a list by its index. <https://redis.io/commands/lindex>
127
 * @method mixed linsert($key, $where, $pivot, $value) Insert an element before or after another element in a list. <https://redis.io/commands/linsert>
128
 * @method mixed llen($key) Get the length of a list. <https://redis.io/commands/llen>
129
 * @method mixed lpop($key) Remove and get the first element in a list. <https://redis.io/commands/lpop>
130
 * @method mixed lpush($key, ...$values) Prepend one or multiple values to a list. <https://redis.io/commands/lpush>
131
 * @method mixed lpush_a($key, array $values) Prepend one or multiple values to a list. <https://redis.io/commands/lpush>
132
 * @method mixed lpushx($key, $value) Prepend a value to a list, only if the list exists. <https://redis.io/commands/lpushx>
133
 * @method mixed lrange($key, $start, $stop) Get a range of elements from a list. <https://redis.io/commands/lrange>
134
 * @method mixed lrem($key, $count, $value) Remove elements from a list. <https://redis.io/commands/lrem>
135
 * @method mixed lset($key, $index, $value) Set the value of an element in a list by its index. <https://redis.io/commands/lset>
136
 * @method mixed ltrim($key, $start, $stop) Trim a list to the specified range. <https://redis.io/commands/ltrim>
137
 * @method mixed mget(...$keys) Get the values of all the given keys. <https://redis.io/commands/mget>
138
 * @method mixed mget_a(array $keys) Get the values of all the given keys. <https://redis.io/commands/mget>
139
 * @method mixed migrate($host, $port, $key, $destinationDb, $timeout, ...$options) Atomically transfer a key from a Redis instance to another one.. <https://redis.io/commands/migrate>
140
 * @method mixed monitor() Listen for all requests received by the server in real time. <https://redis.io/commands/monitor>
141
 * @method mixed move($key, $db) Move a key to another database. <https://redis.io/commands/move>
142
 * @method mixed mset(...$keyValuePairs) Set multiple keys to multiple values. <https://redis.io/commands/mset>
143
 * @method mixed mset_a(array $keyValuePairs) Set multiple keys to multiple values. <https://redis.io/commands/mset>
144
 * @method mixed msetnx(...$keyValuePairs) Set multiple keys to multiple values, only if none of the keys exist. <https://redis.io/commands/msetnx>
145
 * @method mixed msetnx_a(array $keyValuePairs) Set multiple keys to multiple values, only if none of the keys exist. <https://redis.io/commands/msetnx>
146
 * @method mixed multi() Mark the start of a transaction block. <https://redis.io/commands/multi>
147
 * @method mixed object($subcommand, ...$argumentss) Inspect the internals of Redis objects. <https://redis.io/commands/object>
148
 * @method mixed object_a($subcommand, array $argumentss) Inspect the internals of Redis objects. <https://redis.io/commands/object>
149
 * @method mixed persist($key) Remove the expiration from a key. <https://redis.io/commands/persist>
150
 * @method mixed pexpire($key, $milliseconds) Set a key's time to live in milliseconds. <https://redis.io/commands/pexpire>
151
 * @method mixed pexpireat($key, $millisecondsTimestamp) Set the expiration for a key as a UNIX timestamp specified in milliseconds. <https://redis.io/commands/pexpireat>
152
 * @method mixed pfadd($key, ...$elements) Adds the specified elements to the specified HyperLogLog.. <https://redis.io/commands/pfadd>
153
 * @method mixed pfadd_a($key, array $elements) Adds the specified elements to the specified HyperLogLog.. <https://redis.io/commands/pfadd>
154
 * @method mixed pfcount(...$keys) Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s).. <https://redis.io/commands/pfcount>
155
 * @method mixed pfcount_a(array $keys) Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s).. <https://redis.io/commands/pfcount>
156
 * @method mixed pfmerge($destkey, ...$sourcekeys) Merge N different HyperLogLogs into a single one.. <https://redis.io/commands/pfmerge>
157
 * @method mixed pfmerge_a($destkey, array $sourcekeys) Merge N different HyperLogLogs into a single one.. <https://redis.io/commands/pfmerge>
158
 * @method mixed ping($message = null) Ping the server. <https://redis.io/commands/ping>
159
 * @method mixed psetex($key, $milliseconds, $value) Set the value and expiration in milliseconds of a key. <https://redis.io/commands/psetex>
160
 * @method mixed psubscribe(...$patterns) Listen for messages published to channels matching the given patterns. <https://redis.io/commands/psubscribe>
161
 * @method mixed pubsub($subcommand, ...$arguments) Inspect the state of the Pub/Sub subsystem. <https://redis.io/commands/pubsub>
162
 * @method mixed pttl($key) Get the time to live for a key in milliseconds. <https://redis.io/commands/pttl>
163
 * @method mixed publish($channel, $message) Post a message to a channel. <https://redis.io/commands/publish>
164
 * @method mixed punsubscribe(...$patterns) Stop listening for messages posted to channels matching the given patterns. <https://redis.io/commands/punsubscribe>
165
 * @method mixed quit() Close the connection. <https://redis.io/commands/quit>
166
 * @method mixed randomkey() Return a random key from the keyspace. <https://redis.io/commands/randomkey>
167
 * @method mixed readonly() Enables read queries for a connection to a cluster slave node. <https://redis.io/commands/readonly>
168
 * @method mixed readwrite() Disables read queries for a connection to a cluster slave node. <https://redis.io/commands/readwrite>
169
 * @method mixed rename($key, $newkey) Rename a key. <https://redis.io/commands/rename>
170
 * @method mixed renamenx($key, $newkey) Rename a key, only if the new key does not exist. <https://redis.io/commands/renamenx>
171
 * @method mixed restore($key, $ttl, $serializedValue, $REPLACE = null) Create a key using the provided serialized value, previously obtained using DUMP.. <https://redis.io/commands/restore>
172
 * @method mixed role() Return the role of the instance in the context of replication. <https://redis.io/commands/role>
173
 * @method mixed rpop($key) Remove and get the last element in a list. <https://redis.io/commands/rpop>
174
 * @method mixed rpoplpush($source, $destination) Remove the last element in a list, prepend it to another list and return it. <https://redis.io/commands/rpoplpush>
175
 * @method mixed rpush($key, ...$values) Append one or multiple values to a list. <https://redis.io/commands/rpush>
176
 * @method mixed rpush_a($key, array $values) Append one or multiple values to a list. <https://redis.io/commands/rpush>
177
 * @method mixed rpushx($key, $value) Append a value to a list, only if the list exists. <https://redis.io/commands/rpushx>
178
 * @method mixed sadd($key, ...$members) Add one or more members to a set. <https://redis.io/commands/sadd>
179
 * @method mixed sadd_a($key, array $members) Add one or more members to a set. <https://redis.io/commands/sadd>
180
 * @method mixed save() Synchronously save the dataset to disk. <https://redis.io/commands/save>
181
 * @method mixed scard($key) Get the number of members in a set. <https://redis.io/commands/scard>
182
 * @method mixed scriptDebug($option) Set the debug mode for executed scripts.. <https://redis.io/commands/script-debug>
183
 * @method mixed scriptExists(...$sha1s) Check existence of scripts in the script cache.. <https://redis.io/commands/script-exists>
184
 * @method mixed scriptFlush() Remove all the scripts from the script cache.. <https://redis.io/commands/script-flush>
185
 * @method mixed scriptKill() Kill the script currently in execution.. <https://redis.io/commands/script-kill>
186
 * @method mixed scriptLoad($script) Load the specified Lua script into the script cache.. <https://redis.io/commands/script-load>
187
 * @method mixed sdiff(...$keys) Subtract multiple sets. <https://redis.io/commands/sdiff>
188
 * @method mixed sdiffstore($destination, ...$keys) Subtract multiple sets and store the resulting set in a key. <https://redis.io/commands/sdiffstore>
189
 * @method mixed select($index) Change the selected database for the current connection. <https://redis.io/commands/select>
190
 * @method mixed set($key, $value, ...$options) Set the string value of a key. <https://redis.io/commands/set>
191
 * @method mixed setbit($key, $offset, $value) Sets or clears the bit at offset in the string value stored at key. <https://redis.io/commands/setbit>
192
 * @method mixed setex($key, $seconds, $value) Set the value and expiration of a key. <https://redis.io/commands/setex>
193
 * @method mixed setnx($key, $value) Set the value of a key, only if the key does not exist. <https://redis.io/commands/setnx>
194
 * @method mixed setrange($key, $offset, $value) Overwrite part of a string at key starting at the specified offset. <https://redis.io/commands/setrange>
195
 * @method mixed shutdown($saveOption = null) Synchronously save the dataset to disk and then shut down the server. <https://redis.io/commands/shutdown>
196
 * @method mixed sinter(...$keys) Intersect multiple sets. <https://redis.io/commands/sinter>
197
 * @method mixed sinterstore($destination, ...$keys) Intersect multiple sets and store the resulting set in a key. <https://redis.io/commands/sinterstore>
198
 * @method mixed sismember($key, $member) Determine if a given value is a member of a set. <https://redis.io/commands/sismember>
199
 * @method mixed slaveof($host, $port) Make the server a slave of another instance, or promote it as master. <https://redis.io/commands/slaveof>
200
 * @method mixed slowlog($subcommand, $argument = null) Manages the Redis slow queries log. <https://redis.io/commands/slowlog>
201
 * @method mixed smembers($key) Get all the members in a set. <https://redis.io/commands/smembers>
202
 * @method mixed smove($source, $destination, $member) Move a member from one set to another. <https://redis.io/commands/smove>
203
 * @method mixed sort($key, ...$options) Sort the elements in a list, set or sorted set. <https://redis.io/commands/sort>
204
 * @method mixed spop($key, $count = null) Remove and return one or multiple random members from a set. <https://redis.io/commands/spop>
205
 * @method mixed srandmember($key, $count = null) Get one or multiple random members from a set. <https://redis.io/commands/srandmember>
206
 * @method mixed srem($key, ...$members) Remove one or more members from a set. <https://redis.io/commands/srem>
207
 * @method mixed srem_a($key, array $members) Remove one or more members from a set. <https://redis.io/commands/srem>
208
 * @method mixed strlen($key) Get the length of the value stored in a key. <https://redis.io/commands/strlen>
209
 * @method mixed subscribe(...$channels) Listen for messages published to the given channels. <https://redis.io/commands/subscribe>
210
 * @method mixed sunion(...$keys) Add multiple sets. <https://redis.io/commands/sunion>
211
 * @method mixed sunionstore($destination, ...$keys) Add multiple sets and store the resulting set in a key. <https://redis.io/commands/sunionstore>
212
 * @method mixed swapdb($index, $index) Swaps two Redis databases. <https://redis.io/commands/swapdb>
213
 * @method mixed sync() Internal command used for replication. <https://redis.io/commands/sync>
214
 * @method mixed time() Return the current server time. <https://redis.io/commands/time>
215
 * @method mixed touch(...$keys) Alters the last access time of a key(s). Returns the number of existing keys specified.. <https://redis.io/commands/touch>
216
 * @method mixed ttl($key) Get the time to live for a key. <https://redis.io/commands/ttl>
217
 * @method mixed type($key) Determine the type stored at key. <https://redis.io/commands/type>
218
 * @method mixed unsubscribe(...$channels) Stop listening for messages posted to the given channels. <https://redis.io/commands/unsubscribe>
219
 * @method mixed unlink(...$keys) Delete a key asynchronously in another thread. Otherwise it is just as DEL, but non blocking.. <https://redis.io/commands/unlink>
220
 * @method mixed unwatch() Forget about all watched keys. <https://redis.io/commands/unwatch>
221
 * @method mixed wait($numslaves, $timeout) Wait for the synchronous replication of all the write commands sent in the context of the current connection. <https://redis.io/commands/wait>
222
 * @method mixed watch(...$keys) Watch the given keys to determine execution of the MULTI/EXEC block. <https://redis.io/commands/watch>
223
 * @method mixed zadd($key, ...$options) Add one or more members to a sorted set, or update its score if it already exists. <https://redis.io/commands/zadd>
224
 * @method mixed zadd_a($key, array $options) Add one or more members to a sorted set, or update its score if it already exists. <https://redis.io/commands/zadd>
225
 * @method mixed zcard($key) Get the number of members in a sorted set. <https://redis.io/commands/zcard>
226
 * @method mixed zcount($key, $min, $max) Count the members in a sorted set with scores within the given values. <https://redis.io/commands/zcount>
227
 * @method mixed zincrby($key, $increment, $member) Increment the score of a member in a sorted set. <https://redis.io/commands/zincrby>
228
 * @method mixed zinterstore($destination, $numkeys, $key, ...$options) Intersect multiple sorted sets and store the resulting sorted set in a new key. <https://redis.io/commands/zinterstore>
229
 * @method mixed zlexcount($key, $min, $max) Count the number of members in a sorted set between a given lexicographical range. <https://redis.io/commands/zlexcount>
230
 * @method mixed zrange($key, $start, $stop, $WITHSCORES = null) Return a range of members in a sorted set, by index. <https://redis.io/commands/zrange>
231
 * @method mixed zrangebylex($key, $min, $max, $LIMIT = null, $offset = null, $count = null) Return a range of members in a sorted set, by lexicographical range. <https://redis.io/commands/zrangebylex>
232
 * @method mixed zrevrangebylex($key, $max, $min, $LIMIT = null, $offset = null, $count = null) Return a range of members in a sorted set, by lexicographical range, ordered from higher to lower strings.. <https://redis.io/commands/zrevrangebylex>
233
 * @method mixed zrangebyscore($key, $min, $max, $WITHSCORES = null, $LIMIT = null, $offset = null, $count = null) Return a range of members in a sorted set, by score. <https://redis.io/commands/zrangebyscore>
234
 * @method mixed zrank($key, $member) Determine the index of a member in a sorted set. <https://redis.io/commands/zrank>
235
 * @method mixed zrem($key, ...$members) Remove one or more members from a sorted set. <https://redis.io/commands/zrem>
236
 * @method mixed zrem_a($key, array $members) Remove one or more members from a sorted set. <https://redis.io/commands/zrem>
237
 * @method mixed zremrangebylex($key, $min, $max) Remove all members in a sorted set between the given lexicographical range. <https://redis.io/commands/zremrangebylex>
238
 * @method mixed zremrangebyrank($key, $start, $stop) Remove all members in a sorted set within the given indexes. <https://redis.io/commands/zremrangebyrank>
239
 * @method mixed zremrangebyscore($key, $min, $max) Remove all members in a sorted set within the given scores. <https://redis.io/commands/zremrangebyscore>
240
 * @method mixed zrevrange($key, $start, $stop, $WITHSCORES = null) Return a range of members in a sorted set, by index, with scores ordered from high to low. <https://redis.io/commands/zrevrange>
241
 * @method mixed zrevrangebyscore($key, $max, $min, $WITHSCORES = null, $LIMIT = null, $offset = null, $count = null) Return a range of members in a sorted set, by score, with scores ordered from high to low. <https://redis.io/commands/zrevrangebyscore>
242
 * @method mixed zrevrank($key, $member) Determine the index of a member in a sorted set, with scores ordered from high to low. <https://redis.io/commands/zrevrank>
243
 * @method mixed zscore($key, $member) Get the score associated with the given member in a sorted set. <https://redis.io/commands/zscore>
244
 * @method mixed zunionstore($destination, $numkeys, $key, ...$options) Add multiple sorted sets and store the resulting sorted set in a new key. <https://redis.io/commands/zunionstore>
245
 * @method mixed scan($cursor, $MATCH = null, $pattern = null, $COUNT = null, $count = null) Incrementally iterate the keys space. <https://redis.io/commands/scan>
246
 * @method mixed sscan($key, $cursor, $MATCH = null, $pattern = null, $COUNT = null, $count = null) Incrementally iterate Set elements. <https://redis.io/commands/sscan>
247
 * @method mixed hscan($key, $cursor, $MATCH = null, $pattern = null, $COUNT = null, $count = null) Incrementally iterate hash fields and associated values. <https://redis.io/commands/hscan>
248
 * @method mixed zscan($key, $cursor, $MATCH = null, $pattern = null, $COUNT = null, $count = null) Incrementally iterate sorted sets elements and associated scores. <https://redis.io/commands/zscan>
249
 *
250
 */
251
class Connection
252
{
253
    /**
254
     * @var string the hostname or ip address to use for connecting to the redis server. Defaults to 'localhost'.
255
     * If [[unixSocket]] is specified, hostname and [[port]] will be ignored.
256
     */
257
    public $hostname = 'localhost';
258
    /**
259
     * @var integer the port to use for connecting to the redis server. Default port is 6379.
260
     * If [[unixSocket]] is specified, [[hostname]] and port will be ignored.
261
     */
262
    public $port = 6379;
263
    /**
264
     * @var string the unix socket path (e.g. `/var/run/redis/redis.sock`) to use for connecting to the redis server.
265
     * This can be used instead of [[hostname]] and [[port]] to connect to the server using a unix socket.
266
     * If a unix socket path is specified, [[hostname]] and [[port]] will be ignored.
267
     */
268
    public $unixSocket;
269
    /**
270
     * @var string the password for establishing DB connection. Defaults to null meaning no AUTH command is sent.
271
     * See http://redis.io/commands/auth
272
     */
273
    public $password;
274
    /**
275
     * @var integer the redis database to use. This is an integer value starting from 0. Defaults to 0.
276
     */
277
    public $database = 0;
278
    /**
279
     * @var float timeout to use for connection to redis. If not set the timeout set in php.ini will be used: `ini_get("default_socket_timeout")`.
280
     */
281
    public $connectionTimeout = null;
282
    /**
283
     * @var float timeout to use for redis socket when reading and writing data. If not set the php default value will be used.
284
     */
285
    public $dataTimeout = null;
286
    /**
287
     * @var integer Bitmask field which may be set to any combination of connection flags passed to [stream_socket_client()](http://php.net/manual/en/function.stream-socket-client.php).
288
     * Currently the select of connection flags is limited to `STREAM_CLIENT_CONNECT` (default), `STREAM_CLIENT_ASYNC_CONNECT` and `STREAM_CLIENT_PERSISTENT`.
289
     *
290
     * > Warning: `STREAM_CLIENT_PERSISTENT` will make PHP reuse connections to the same server. If you are using multiple
291
     * > connection objects to refer to different redis [[$database|databases]] on the same [[port]], redis commands may
292
     * > get executed on the wrong database. `STREAM_CLIENT_PERSISTENT` is only safe to use if you use only one database.
293
     * >
294
     * > You may still use persistent connections in this case when disambiguating ports as described
295
     * > in [a comment on the PHP manual](http://php.net/manual/en/function.stream-socket-client.php#105393)
296
     * > e.g. on the connection used for session storage, specify the port as:
297
     * >
298
     * > ```php
299
     * > 'port' => '6379/session'
300
     * > ```
301
     *
302
     * @see http://php.net/manual/en/function.stream-socket-client.php
303
     */
304
    public $socketClientFlags = STREAM_CLIENT_CONNECT;
305
    /**
306
     * @var integer The number of times a command execution should be retried when a connection failure occurs.
307
     * This is used in [[executeCommand()]] when a [[SocketException]] is thrown.
308
     * Defaults to 0 meaning no retries on failure.
309
     */
310
    public $retries = 0;
311
312
    /**
313
     * @var array List of available redis commands.
314
     * @see http://redis.io/commands
315
     */
316
    public $redisCommands = [
317
        'APPEND', // Append a value to a key
318
        'AUTH', // Authenticate to the server
319
        'BGREWRITEAOF', // Asynchronously rewrite the append-only file
320
        'BGSAVE', // Asynchronously save the dataset to disk
321
        'BITCOUNT', // Count set bits in a string
322
        'BITFIELD', // Perform arbitrary bitfield integer operations on strings
323
        'BITOP', // Perform bitwise operations between strings
324
        'BITPOS', // Find first bit set or clear in a string
325
        'BLPOP', // Remove and get the first element in a list, or block until one is available
326
        'BRPOP', // Remove and get the last element in a list, or block until one is available
327
        'BRPOPLPUSH', // Pop a value from a list, push it to another list and return it; or block until one is available
328
        'CLIENT KILL', // Kill the connection of a client
329
        'CLIENT LIST', // Get the list of client connections
330
        'CLIENT GETNAME', // Get the current connection name
331
        'CLIENT PAUSE', // Stop processing commands from clients for some time
332
        'CLIENT REPLY', // Instruct the server whether to reply to commands
333
        'CLIENT SETNAME', // Set the current connection name
334
        'CLUSTER ADDSLOTS', // Assign new hash slots to receiving node
335
        'CLUSTER COUNTKEYSINSLOT', // Return the number of local keys in the specified hash slot
336
        'CLUSTER DELSLOTS', // Set hash slots as unbound in receiving node
337
        'CLUSTER FAILOVER', // Forces a slave to perform a manual failover of its master.
338
        'CLUSTER FORGET', // Remove a node from the nodes table
339
        'CLUSTER GETKEYSINSLOT', // Return local key names in the specified hash slot
340
        'CLUSTER INFO', // Provides info about Redis Cluster node state
341
        'CLUSTER KEYSLOT', // Returns the hash slot of the specified key
342
        'CLUSTER MEET', // Force a node cluster to handshake with another node
343
        'CLUSTER NODES', // Get Cluster config for the node
344
        'CLUSTER REPLICATE', // Reconfigure a node as a slave of the specified master node
345
        'CLUSTER RESET', // Reset a Redis Cluster node
346
        'CLUSTER SAVECONFIG', // Forces the node to save cluster state on disk
347
        'CLUSTER SETSLOT', // Bind a hash slot to a specific node
348
        'CLUSTER SLAVES', // List slave nodes of the specified master node
349
        'CLUSTER SLOTS', // Get array of Cluster slot to node mappings
350
        'COMMAND', // Get array of Redis command details
351
        'COMMAND COUNT', // Get total number of Redis commands
352
        'COMMAND GETKEYS', // Extract keys given a full Redis command
353
        'COMMAND INFO', // Get array of specific Redis command details
354
        'CONFIG GET', // Get the value of a configuration parameter
355
        'CONFIG REWRITE', // Rewrite the configuration file with the in memory configuration
356
        'CONFIG SET', // Set a configuration parameter to the given value
357
        'CONFIG RESETSTAT', // Reset the stats returned by INFO
358
        'DBSIZE', // Return the number of keys in the selected database
359
        'DEBUG OBJECT', // Get debugging information about a key
360
        'DEBUG SEGFAULT', // Make the server crash
361
        'DECR', // Decrement the integer value of a key by one
362
        'DECRBY', // Decrement the integer value of a key by the given number
363
        'DEL', // Delete a key
364
        'DISCARD', // Discard all commands issued after MULTI
365
        'DUMP', // Return a serialized version of the value stored at the specified key.
366
        'ECHO', // Echo the given string
367
        'EVAL', // Execute a Lua script server side
368
        'EVALSHA', // Execute a Lua script server side
369
        'EXEC', // Execute all commands issued after MULTI
370
        'EXISTS', // Determine if a key exists
371
        'EXPIRE', // Set a key's time to live in seconds
372
        'EXPIREAT', // Set the expiration for a key as a UNIX timestamp
373
        'FLUSHALL', // Remove all keys from all databases
374
        'FLUSHDB', // Remove all keys from the current database
375
        'GEOADD', // Add one or more geospatial items in the geospatial index represented using a sorted set
376
        'GEOHASH', // Returns members of a geospatial index as standard geohash strings
377
        'GEOPOS', // Returns longitude and latitude of members of a geospatial index
378
        'GEODIST', // Returns the distance between two members of a geospatial index
379
        'GEORADIUS', // Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a point
380
        'GEORADIUSBYMEMBER', // Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a member
381
        'GET', // Get the value of a key
382
        'GETBIT', // Returns the bit value at offset in the string value stored at key
383
        'GETRANGE', // Get a substring of the string stored at a key
384
        'GETSET', // Set the string value of a key and return its old value
385
        'HDEL', // Delete one or more hash fields
386
        'HEXISTS', // Determine if a hash field exists
387
        'HGET', // Get the value of a hash field
388
        'HGETALL', // Get all the fields and values in a hash
389
        'HINCRBY', // Increment the integer value of a hash field by the given number
390
        'HINCRBYFLOAT', // Increment the float value of a hash field by the given amount
391
        'HKEYS', // Get all the fields in a hash
392
        'HLEN', // Get the number of fields in a hash
393
        'HMGET', // Get the values of all the given hash fields
394
        'HMSET', // Set multiple hash fields to multiple values
395
        'HSET', // Set the string value of a hash field
396
        'HSETNX', // Set the value of a hash field, only if the field does not exist
397
        'HSTRLEN', // Get the length of the value of a hash field
398
        'HVALS', // Get all the values in a hash
399
        'INCR', // Increment the integer value of a key by one
400
        'INCRBY', // Increment the integer value of a key by the given amount
401
        'INCRBYFLOAT', // Increment the float value of a key by the given amount
402
        'INFO', // Get information and statistics about the server
403
        'KEYS', // Find all keys matching the given pattern
404
        'LASTSAVE', // Get the UNIX time stamp of the last successful save to disk
405
        'LINDEX', // Get an element from a list by its index
406
        'LINSERT', // Insert an element before or after another element in a list
407
        'LLEN', // Get the length of a list
408
        'LPOP', // Remove and get the first element in a list
409
        'LPUSH', // Prepend one or multiple values to a list
410
        'LPUSHX', // Prepend a value to a list, only if the list exists
411
        'LRANGE', // Get a range of elements from a list
412
        'LREM', // Remove elements from a list
413
        'LSET', // Set the value of an element in a list by its index
414
        'LTRIM', // Trim a list to the specified range
415
        'MGET', // Get the values of all the given keys
416
        'MIGRATE', // Atomically transfer a key from a Redis instance to another one.
417
        'MONITOR', // Listen for all requests received by the server in real time
418
        'MOVE', // Move a key to another database
419
        'MSET', // Set multiple keys to multiple values
420
        'MSETNX', // Set multiple keys to multiple values, only if none of the keys exist
421
        'MULTI', // Mark the start of a transaction block
422
        'OBJECT', // Inspect the internals of Redis objects
423
        'PERSIST', // Remove the expiration from a key
424
        'PEXPIRE', // Set a key's time to live in milliseconds
425
        'PEXPIREAT', // Set the expiration for a key as a UNIX timestamp specified in milliseconds
426
        'PFADD', // Adds the specified elements to the specified HyperLogLog.
427
        'PFCOUNT', // Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s).
428
        'PFMERGE', // Merge N different HyperLogLogs into a single one.
429
        'PING', // Ping the server
430
        'PSETEX', // Set the value and expiration in milliseconds of a key
431
        'PSUBSCRIBE', // Listen for messages published to channels matching the given patterns
432
        'PUBSUB', // Inspect the state of the Pub/Sub subsystem
433
        'PTTL', // Get the time to live for a key in milliseconds
434
        'PUBLISH', // Post a message to a channel
435
        'PUNSUBSCRIBE', // Stop listening for messages posted to channels matching the given patterns
436
        'QUIT', // Close the connection
437
        'RANDOMKEY', // Return a random key from the keyspace
438
        'READONLY', // Enables read queries for a connection to a cluster slave node
439
        'READWRITE', // Disables read queries for a connection to a cluster slave node
440
        'RENAME', // Rename a key
441
        'RENAMENX', // Rename a key, only if the new key does not exist
442
        'RESTORE', // Create a key using the provided serialized value, previously obtained using DUMP.
443
        'ROLE', // Return the role of the instance in the context of replication
444
        'RPOP', // Remove and get the last element in a list
445
        'RPOPLPUSH', // Remove the last element in a list, prepend it to another list and return it
446
        'RPUSH', // Append one or multiple values to a list
447
        'RPUSHX', // Append a value to a list, only if the list exists
448
        'SADD', // Add one or more members to a set
449
        'SAVE', // Synchronously save the dataset to disk
450
        'SCARD', // Get the number of members in a set
451
        'SCRIPT DEBUG', // Set the debug mode for executed scripts.
452
        'SCRIPT EXISTS', // Check existence of scripts in the script cache.
453
        'SCRIPT FLUSH', // Remove all the scripts from the script cache.
454
        'SCRIPT KILL', // Kill the script currently in execution.
455
        'SCRIPT LOAD', // Load the specified Lua script into the script cache.
456
        'SDIFF', // Subtract multiple sets
457
        'SDIFFSTORE', // Subtract multiple sets and store the resulting set in a key
458
        'SELECT', // Change the selected database for the current connection
459
        'SET', // Set the string value of a key
460
        'SETBIT', // Sets or clears the bit at offset in the string value stored at key
461
        'SETEX', // Set the value and expiration of a key
462
        'SETNX', // Set the value of a key, only if the key does not exist
463
        'SETRANGE', // Overwrite part of a string at key starting at the specified offset
464
        'SHUTDOWN', // Synchronously save the dataset to disk and then shut down the server
465
        'SINTER', // Intersect multiple sets
466
        'SINTERSTORE', // Intersect multiple sets and store the resulting set in a key
467
        'SISMEMBER', // Determine if a given value is a member of a set
468
        'SLAVEOF', // Make the server a slave of another instance, or promote it as master
469
        'SLOWLOG', // Manages the Redis slow queries log
470
        'SMEMBERS', // Get all the members in a set
471
        'SMOVE', // Move a member from one set to another
472
        'SORT', // Sort the elements in a list, set or sorted set
473
        'SPOP', // Remove and return one or multiple random members from a set
474
        'SRANDMEMBER', // Get one or multiple random members from a set
475
        'SREM', // Remove one or more members from a set
476
        'STRLEN', // Get the length of the value stored in a key
477
        'SUBSCRIBE', // Listen for messages published to the given channels
478
        'SUNION', // Add multiple sets
479
        'SUNIONSTORE', // Add multiple sets and store the resulting set in a key
480
        'SWAPDB', // Swaps two Redis databases
481
        'SYNC', // Internal command used for replication
482
        'TIME', // Return the current server time
483
        'TOUCH', // Alters the last access time of a key(s). Returns the number of existing keys specified.
484
        'TTL', // Get the time to live for a key
485
        'TYPE', // Determine the type stored at key
486
        'UNSUBSCRIBE', // Stop listening for messages posted to the given channels
487
        'UNLINK', // Delete a key asynchronously in another thread. Otherwise it is just as DEL, but non blocking.
488
        'UNWATCH', // Forget about all watched keys
489
        'WAIT', // Wait for the synchronous replication of all the write commands sent in the context of the current connection
490
        'WATCH', // Watch the given keys to determine execution of the MULTI/EXEC block
491
        'ZADD', // Add one or more members to a sorted set, or update its score if it already exists
492
        'ZCARD', // Get the number of members in a sorted set
493
        'ZCOUNT', // Count the members in a sorted set with scores within the given values
494
        'ZINCRBY', // Increment the score of a member in a sorted set
495
        'ZINTERSTORE', // Intersect multiple sorted sets and store the resulting sorted set in a new key
496
        'ZLEXCOUNT', // Count the number of members in a sorted set between a given lexicographical range
497
        'ZRANGE', // Return a range of members in a sorted set, by index
498
        'ZRANGEBYLEX', // Return a range of members in a sorted set, by lexicographical range
499
        'ZREVRANGEBYLEX', // Return a range of members in a sorted set, by lexicographical range, ordered from higher to lower strings.
500
        'ZRANGEBYSCORE', // Return a range of members in a sorted set, by score
501
        'ZRANK', // Determine the index of a member in a sorted set
502
        'ZREM', // Remove one or more members from a sorted set
503
        'ZREMRANGEBYLEX', // Remove all members in a sorted set between the given lexicographical range
504
        'ZREMRANGEBYRANK', // Remove all members in a sorted set within the given indexes
505
        'ZREMRANGEBYSCORE', // Remove all members in a sorted set within the given scores
506
        'ZREVRANGE', // Return a range of members in a sorted set, by index, with scores ordered from high to low
507
        'ZREVRANGEBYSCORE', // Return a range of members in a sorted set, by score, with scores ordered from high to low
508
        'ZREVRANK', // Determine the index of a member in a sorted set, with scores ordered from high to low
509
        'ZSCORE', // Get the score associated with the given member in a sorted set
510
        'ZUNIONSTORE', // Add multiple sorted sets and store the resulting sorted set in a new key
511
        'SCAN', // Incrementally iterate the keys space
512
        'SSCAN', // Incrementally iterate Set elements
513
        'HSCAN', // Incrementally iterate hash fields and associated values
514
        'ZSCAN', // Incrementally iterate sorted sets elements and associated scores
515
    ];
516
517
    /**
518
     * @var bool|Resource
519
     */
520
    private $_socket = false;
521
522
    /**
523
     * Connection constructor.
524
     * @param array $config
525
     */
526
    public function __construct($config = [])
527
    {
528
        if (!empty($config)) {
529
            foreach ($config as $name => $value) {
530
                $this->$name = $value;
531
            }
532
        }
533
        $this->init();
534
    }
535
536
    /**
537
     * Initializes the object.
538
     * This method is invoked at the end of the constructor after the object is initialized with the
539
     * given configuration.
540
     */
541
    public function init()
542
    {
543
    }
544
545
    /**
546
     * Closes the connection when this component is being serialized.
547
     * @return array
548
     * @throws \Exception
549
     */
550
    public function __sleep()
551
    {
552
        $this->close();
553
        return array_keys(get_object_vars($this));
554
    }
555
556
    /**
557
     * Returns a value indicating whether the DB connection is established.
558
     * @return bool whether the DB connection is established
559
     */
560
    public function getIsActive()
561
    {
562
        return $this->_socket !== false;
563
    }
564
565
    /**
566
     * Establishes a DB connection.
567
     * It does nothing if a DB connection has already been established.
568
     * @throws RedisException if connection fails
569
     * @throws \Exception
570
     */
571
    public function open()
572
    {
573
        if ($this->_socket !== false) {
574
            return;
575
        }
576
        $connection = ($this->unixSocket ?: $this->hostname . ':' . $this->port) . ', database=' . $this->database;
577
        $this->_socket = @stream_socket_client(
578
            $this->unixSocket ? 'unix://' . $this->unixSocket : 'tcp://' . $this->hostname . ':' . $this->port,
579
            $errorNumber,
580
            $errorDescription,
581
            $this->connectionTimeout ? $this->connectionTimeout : ini_get('default_socket_timeout'),
0 ignored issues
show
It seems like $this->connectionTimeout...efault_socket_timeout') can also be of type string; however, parameter $timeout of stream_socket_client() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

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

581
            /** @scrutinizer ignore-type */ $this->connectionTimeout ? $this->connectionTimeout : ini_get('default_socket_timeout'),
Loading history...
582
            $this->socketClientFlags
583
        );
584
        if ($this->_socket) {
585
            if ($this->dataTimeout !== null) {
586
                stream_set_timeout($this->_socket, $timeout = (int) $this->dataTimeout, (int) (($this->dataTimeout - $timeout) * 1000000));
587
            }
588
            if ($this->password !== null) {
589
                $this->executeCommand('AUTH', [$this->password]);
590
            }
591
            if ($this->database !== null) {
592
                $this->executeCommand('SELECT', [$this->database]);
593
            }
594
        } else {
595
            $message = 'Failed to open DB connection.';
596
            throw new RedisException($message, $errorDescription, $errorNumber);
597
        }
598
    }
599
600
    /**
601
     * Closes the currently active DB connection.
602
     * It does nothing if the connection is already closed.
603
     * @throws \Exception
604
     */
605
    public function close()
606
    {
607
        if ($this->_socket !== false) {
608
            $connection = ($this->unixSocket ?: $this->hostname . ':' . $this->port) . ', database=' . $this->database;
609
            try {
610
                $this->executeCommand('QUIT');
611
            } catch (SocketRedisException $e) {
612
                // ignore errors when quitting a closed connection
613
            }
614
            fclose($this->_socket);
0 ignored issues
show
It seems like $this->_socket can also be of type true; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

614
            fclose(/** @scrutinizer ignore-type */ $this->_socket);
Loading history...
615
            $this->_socket = false;
616
        }
617
    }
618
619
    /**
620
     * Returns the name of the DB driver for the current [[dsn]].
621
     * @return string name of the DB driver
622
     */
623
    public function getDriverName()
624
    {
625
        return 'redis';
626
    }
627
628
    /**
629
     * Allows issuing all supported commands via magic methods.
630
     *
631
     * ```php
632
     * $redis->hmset('test_collection', 'key1', 'val1', 'key2', 'val2')
633
     * OR
634
     * $redis->hmset(['test_collection', 'key1', 'val1', 'key2', 'val2'])
635
     * OR
636
     * $redis->hmset('test_collection', ['key1', 'val1', 'key2', 'val2'])
637
     * ```
638
     *
639
     * @param string $name name of the missing method to execute
640
     * @param array $params method call arguments
641
     * @return mixed
642
     * @throws RedisException
643
     * @throws \Exception
644
     */
645
    public function __call($name, $params)
646
    {
647
        if (false !== strpos($name, '_a')) {
648
            $name = substr($name, 0, -2);
649
            $params = $this->normalizeParams($name, $params);
650
        }
651
        $redisCommand = strtoupper(Inflector::camel2words($name, false));
652
        if (in_array($redisCommand, $this->redisCommands)) {
653
            return $this->executeCommand($redisCommand, $params);
654
        }
655
656
        throw new RedisException("method {$name} not found");
657
    }
658
659
    /**
660
     * 如果参数是二维数组,转化为一维,为了支持函数调用时传数组参数
661
     * @param $name
662
     * @param $params
663
     * @return array
664
     */
665
    private function normalizeParams($name, $params)
666
    {
667
        $arguments = [];
668
        foreach ($params as $args) {
669
            if (is_array($args)) {
670
                foreach ($args as $arg) {
671
                    $arguments[] = $arg;
672
                }
673
            } else {
674
                $arguments[] = $args;
675
            }
676
        }
677
        return $arguments;
678
    }
679
680
    /**
681
     * Executes a redis command.
682
     * For a list of available commands and their parameters see http://redis.io/commands.
683
     *
684
     * The params array should contain the params separated by white space, e.g. to execute
685
     * `SET mykey somevalue NX` call the following:
686
     *
687
     * ```php
688
     * $redis->executeCommand('SET', ['mykey', 'somevalue', 'NX']);
689
     * ```
690
     *
691
     * @param string $name the name of the command
692
     * @param array $params list of parameters for the command
693
     * @return array|bool|null|string Dependent on the executed command this method
694
     * will return different data types:
695
     *
696
     * - `true` for commands that return "status reply" with the message `'OK'` or `'PONG'`.
697
     * - `string` for commands that return "status reply" that does not have the message `OK` (since version 2.0.1).
698
     * - `string` for commands that return "integer reply"
699
     *   as the value is in the range of a signed 64 bit integer.
700
     * - `string` or `null` for commands that return "bulk reply".
701
     * - `array` for commands that return "Multi-bulk replies".
702
     *
703
     * <number of arguments> CR LF
704
     * $<number of bytes of argument 1> CR LF
705
     * <argument data> CR LF
706
     *   ...
707
     * $<number of bytes of argument N> CR LF
708
     * <argument data> CR LF
709
     *
710
     * See [redis protocol description](http://redis.io/topics/protocol)
711
     * for details on the mentioned reply types.
712
     * @throws RedisException for commands that return [error reply](http://redis.io/topics/protocol#error-reply).
713
     * @throws \Exception
714
     */
715
    public function executeCommand($name, $params = [])
716
    {
717
        $this->open();
718
719
        $params = array_merge(explode(' ', $name), $params);
720
        $command = '*' . count($params) . "\r\n";
721
        foreach ($params as $arg) {
722
            $command .= '$' . mb_strlen($arg, '8bit') . "\r\n" . $arg . "\r\n";
723
        }
724
725
        if ($this->retries > 0) {
726
            $tries = $this->retries;
727
            while ($tries-- > 0) {
728
                try {
729
                    return $this->sendCommandInternal($command, $params);
730
                } catch (SocketRedisException $e) {
731
                    // backup retries, fail on commands that fail inside here
732
                    $retries = $this->retries;
733
                    $this->retries = 0;
734
                    $this->close();
735
                    $this->open();
736
                    $this->retries = $retries;
737
                }
738
            }
739
        }
740
        return $this->sendCommandInternal($command, $params);
741
    }
742
743
    /**
744
     * Sends RAW command string to the server.
745
     * @throws SocketRedisException on connection error.
746
     * @throws \Exception
747
     */
748
    private function sendCommandInternal($command, $params)
749
    {
750
        $written = @fwrite($this->_socket, $command);
0 ignored issues
show
It seems like $this->_socket can also be of type boolean; however, parameter $handle of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

750
        $written = @fwrite(/** @scrutinizer ignore-type */ $this->_socket, $command);
Loading history...
751
        if ($written === false) {
752
            throw new SocketRedisException("Failed to write to socket.\nRedis command was: " . $command);
753
        }
754
        if ($written !== ($len = mb_strlen($command, '8bit'))) {
755
            throw new SocketRedisException("Failed to write to socket. $written of $len bytes written.\nRedis command was: " . $command);
756
        }
757
        return $this->parseResponse(implode(' ', $params));
758
    }
759
760
    /**
761
     * For Simple Strings the first byte of the reply is "+"   "+OK\r\n"
762
     * For Errors the first byte of the reply is "-"           "-Error message\r\n"
763
     * For Integers the first byte of the reply is ":"         ":1000\r\n"
764
     * For Bulk Strings the first byte of the reply is "$"     "$6\r\nfoobar\r\n" "$0\r\n\r\n" "$-1\r\n"
765
     * For Arrays the first byte of the reply is "*"           "*0\r\n" "*-1\r\n" *3\r\n:1\r\n:2\r\n$6\r\nfoobar\r\n
766
     * @param string $command
767
     * @return mixed
768
     * @throws RedisException on error
769
     */
770
    private function parseResponse($command)
771
    {
772
        if (($line = fgets($this->_socket)) === false) {
0 ignored issues
show
It seems like $this->_socket can also be of type boolean; however, parameter $handle of fgets() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

772
        if (($line = fgets(/** @scrutinizer ignore-type */ $this->_socket)) === false) {
Loading history...
773
            throw new SocketRedisException("Failed to read from socket.\nRedis command was: " . $command);
774
        }
775
        $type = $line[0];
776
        $line = mb_substr($line, 1, -2, '8bit');
777
        switch ($type) {
778
            case '+': // Status reply
779
                if ($line === 'OK' || $line === 'PONG') {
780
                    return true;
781
                } else {
782
                    return $line;
783
                }
784
            case '-': // Error reply
785
                throw new RedisException("Redis error: " . $line . "\nRedis command was: " . $command);
786
            case ':': // Integer reply
787
                // no cast to int as it is in the range of a signed 64 bit integer
788
                return $line;
789
            case '$': // Bulk replies
790
                if ($line == '-1') {
791
                    return null;
792
                }
793
                $length = (int)$line + 2;
794
                $data = '';
795
                while ($length > 0) {
796
                    if (($block = fread($this->_socket, $length)) === false) {
0 ignored issues
show
It seems like $this->_socket can also be of type boolean; however, parameter $handle of fread() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

796
                    if (($block = fread(/** @scrutinizer ignore-type */ $this->_socket, $length)) === false) {
Loading history...
797
                        throw new SocketRedisException("Failed to read from socket.\nRedis command was: " . $command);
798
                    }
799
                    $data .= $block;
800
                    $length -= mb_strlen($block, '8bit');
801
                }
802
803
                return mb_substr($data, 0, -2, '8bit');
804
            case '*': // Multi-bulk replies
805
                $count = (int) $line;
806
                $data = [];
807
                for ($i = 0; $i < $count; $i++) {
808
                    $data[] = $this->parseResponse($command);
809
                }
810
811
                return $data;
812
            default:
813
                throw new RedisException('Received illegal data from redis: ' . $line . "\nRedis command was: " . $command);
814
        }
815
    }
816
}
817