8000 Implement _call command · jrtkcoder/phpredis@e8bc6fd · GitHub
[go: up one dir, main page]

Skip to content

Commit e8bc6fd

Browse files
committed
Implement _call command
* References: issues phpredis#281 and phpredis#300. * Currently requires the command to end with \r\n. * No prefixing/serializing is done.
1 parent c37a7d3 commit e8bc6fd

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

README.markdown

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2978,3 +2978,29 @@ serializing values, and you return something from redis in a LUA script that is
29782978
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
29792979
$redis->_unserialize('a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}'); // Will return Array(1,2,3)
29802980
~~~
2981+
2982+
2983+
## Other
2984+
2985+
* [_call](#) - Executes a custom command
2986+
2987+
### _call
2988+
-----
2989+
_**Description**_: Sends a custom command to Redis.
2990+
2991+
This method is only useful if a particular command is not implemented by phpredis.
2992+
`_call` is limited: the command is not sanitized or checked, the keys are not prefixed and the data is not serialized.
2993+
2994+
##### *Parameters*
2995+
*command* string. The command to send to Redis, using the [Redis protocol](http://redis.io/topics/protocol).
2996+
2997+
##### *Return value*
2998+
The result of the command as returned by Redis. Its type depends on the command.
2999+
3000+
##### *Examples*
3001+
~~~
3002+
$redis->set('x', 'hello');
3003+
$redis->_call("GET x\r\n"); // returns str(5) "hello"
3004+
$redis->set('c', '100');
3005+
$redis->_call("INCR c\r\n"); // returns int(101)
3006+
~~~

php_redis.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ PHP_METHOD(Redis, getLastError);
142142
PHP_METHOD(Redis, clearLastError);
143143
PHP_METHOD(Redis, _prefix);
144144
PHP_METHOD(Redis, _unserialize);
145+
PHP_METHOD(Redis, _call);
145146

146147
PHP_METHOD(Redis, mset);
147148
PHP_METHOD(Redis, msetnx);

redis.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ static zend_function_entry redis_functions[] = {
226226

227227
PHP_ME(Redis, _prefix, NULL, ZEND_ACC_PUBLIC)
228228
PHP_ME(Redis, _unserialize, NULL, ZEND_ACC_PUBLIC)
229+
PHP_ME(Redis, _call, NULL, ZEND_ACC_PUBLIC)
229230

230231
PHP_ME(Redis, client, NULL, ZEND_ACC_PUBLIC)
231232

@@ -6059,6 +6060,47 @@ PHP_METHOD(Redis, script) {
60596060
REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
60606061
}
60616062

6063+
/* {{{ proto variant Redis::_call(string command)
6064+
*/
6065+
PHP_METHOD(Redis, _call)
6066+
{
6067+
zval *object;
6068+
RedisSock *redis_sock;
6069+
char *cmd;
6070+
int cmd_len;
6071+
6072+
// Attempt to parse parameters
6073+
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",
6074+
&object, redis_ce, &cmd, &cmd_len) == FAILURE) {
6075+
RETURN_FALSE;
6076+
}
6077+
6078+
// Attempt to grab socket
6079+
if (redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) {
6080+
RETURN_FALSE;
6081+
}
6082+
6083+
// This is REDIS_PROCESS_REQUEST() without calling free(cmd);
6084+
IF_MULTI_OR_ATOMIC() {
6085+
if(redis_sock_write(redis_sock, cmd, cmd_len TSRMLS_CC) < 0) {
6086+
RETURN_FALSE;
6087+
}
6088+
}
6089+
IF_PIPELINE() {
6090+
PIPELINE_ENQUEUE_COMMAND(cmd, cmd_len);
6091+
}
6092+
6093+
IF_ATOMIC() {
6094+
if(redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL) < 0) {
6095+
RETURN_FALSE;
6096+
}
6097+
}
6098+
REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
6099+
}
6100+
6101+
/* }}}
6102+
*/
6103+
60626104
/* {{{ proto DUMP key
60636105
*/
60646106
PHP_METHOD(Redis, dump) {

tests/TestRedis.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3438,6 +3438,28 @@ public function testReadTimeoutOption() {
34383438
$this->assertEquals(12.3, $this->redis->getOption(Redis::OPT_READ_TIMEOUT));
34393439
}
34403440

3441+
public function testGenericCall() {
3442+
3443+
$this->redis->delete('str', 'counter', 'list', 'set', 'zset', 'hash');
3444+
3445+
// initialise data
3446+
$this->redis->set('str', 'val');
3447+
$this->redis->incrBy('counter', 42);
3448+
$this->redis->rpush('list', 'a', 'b', 'c');
3449+
$this->redis->sadd('set', 'a', 'b', 'c');
3450+
$this->redis->hmset('hash', array('a' => 'x', 'b' => 'y', 'c' => 'z'));
3451+
3452+
// test various commands
3453+
$this->assertEquals("val", $this->redis->_call("GET str\r\n"));
3454+
$this->assertEquals("42", $this->redis->_call("GET counter\r\n"));
3455+
$this->assertEquals(43, $this->redis->_call("INCR counter\r\n"));
3456+
$this->assertEquals(array('a', 'b', 'c'), $this->redis->_call("LRANGE list 0 -1\r\n"));
3457+
$smembers = $this->redis->_call("SMEMBERS set\r\n");
3458+
sort($smembers);
3459+
$this->assertEquals(array('a', 'b', 'c'), $smembers);
3460+
$this->assertEquals(array('x', 'y', 'z', FALSE), $this->redis->_call("HMGET hash a b c d\r\n"));
3461+
}
3462+
34413463
}
34423464

34433465
exit(TestSuite::run("Redis_Test"));

0 commit comments

Comments
 (0)
0