浏览代码

Improve URI parsing for connection parameters.

Using PHP's "parse_str()" to parse the query string is slightly more
efficient then our own code especially when the number of fields in
the query string grows, with the additional benefit of supporting
arrays for values when brackets are present in fieldnames.

So after this commit, providing this URI string:

  $string = 'tcp://127.0.0.1?metavars[]=foo&metavars[]=hoge';

Is equivalent to providing the following named array:

  $array = [
    'scheme' => 'tcp',
    'host' => '127.0.0.1',
    'metavars' => ['foo', 'hoge'],
  ];

Other improvements are that parsing does not break when the value of a
field contains one or more "=" and empty or incomplete "key=value"
pairs result in an empty string for "key".
Daniele Alessandri 11 年之前
父节点
当前提交
09cb6677e2
共有 3 个文件被更改,包括 62 次插入5 次删除
  1. 7 0
      CHANGELOG.md
  2. 3 5
      lib/Predis/Connection/ConnectionParameters.php
  3. 52 0
      tests/Predis/Connection/ConnectionParametersTest.php

+ 7 - 0
CHANGELOG.md

@@ -19,6 +19,13 @@ v0.8.5 (2013-xx-xx)
   responses are not parsed, which means arguments must follow the signature of
   the command as defined by Redis and complex responses are left untouched.
 
+- URI parsing for connection parameters has been improved and has slightly less
+  overhead when the number of fields in the querystring grows. New features are:
+
+    - Parsing does not break when value of a field contains one or more "=".
+    - Repeated fieldnames using [] produce an array of values.
+    - Empty or incomplete "key=value" pairs result in an empty string for "key".
+
 - Various improvements and fixes to the redis-cluster connection backend:
 
     - __FIX__: the `ASKING` command is sent upon -ASK redirections.

+ 3 - 5
lib/Predis/Connection/ConnectionParameters.php

@@ -119,12 +119,10 @@ class ConnectionParameters implements ConnectionParametersInterface
         }
 
         if (isset($parsed['query'])) {
-            foreach (explode('&', $parsed['query']) as $kv) {
-                @list($k, $v) = explode('=', $kv);
-                $parsed[$k] = $v;
-            }
-
+            parse_str($parsed['query'], $queryarray);
             unset($parsed['query']);
+
+            $parsed = array_merge($parsed, $queryarray);
         }
 
         return $parsed;

+ 52 - 0
tests/Predis/Connection/ConnectionParametersTest.php

@@ -158,6 +158,58 @@ class ParametersTest extends PredisTestCase
         $this->assertSame($expected, ConnectionParameters::parseURI($uri));
     }
 
+    /**
+     * @group disconnected
+     */
+    public function testParsingURIWithIncompletePairInQueryString()
+    {
+        $uri = 'tcp://10.10.10.10?persistent=1&foo=&bar';
+
+        $expected = array(
+            'scheme' => 'tcp',
+            'host' => '10.10.10.10',
+            'persistent' => '1',
+            'foo' => '',
+            'bar' => '',
+        );
+
+        $this->assertSame($expected, ConnectionParameters::parseURI($uri));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testParsingURIWithMoreThanOneEqualSignInQueryStringPairValue()
+    {
+        $uri = 'tcp://10.10.10.10?foobar=a=b=c&persistent=1';
+
+        $expected = array(
+            'scheme' => 'tcp',
+            'host' => '10.10.10.10',
+            'foobar' => 'a=b=c',
+            'persistent' => '1',
+        );
+
+        $this->assertSame($expected, ConnectionParameters::parseURI($uri));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testParsingURIWhenQueryStringHasBracketsInFieldnames()
+    {
+        $uri = 'tcp://10.10.10.10?persistent=1&metavars[]=foo&metavars[]=hoge';
+
+        $expected = array(
+            'scheme' => 'tcp',
+            'host' => '10.10.10.10',
+            'persistent' => '1',
+            'metavars' => array('foo', 'hoge'),
+        );
+
+        $this->assertSame($expected, ConnectionParameters::parseURI($uri));
+    }
+
     /**
      * @group disconnected
      * @expectedException Predis\ClientException