Skip to content

Commit a5c94f8

Browse files
authored
Feat: Flat query parser (#5)
1 parent 21b5173 commit a5c94f8

5 files changed

Lines changed: 94 additions & 7 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Because I needed an intuitive way to add or remove parameters from a query strin
1515

1616
Oh, and, I also wanted that `['foos' => ['foo', 'bar']]` resolved to `foos[]=foo&foos[]=bar` instead of `foos[0]=foo&foos[1]=bar`, unlike many libraries do.
1717

18-
This behavior is not the default one of that library, but there's an [easy way to change it](doc/RenderAsString.md#change-renderer).
18+
Thanks to object-oriented design, you can define the way query strings are [parsed](doc/Instantiation.md) and [rendered](doc/RenderAsString.md#change-renderer).
1919

2020
## Usage
2121

@@ -44,15 +44,15 @@ print $qs; // foo=foofoo&ho=hi
4444

4545
## Documentation
4646

47-
[Instanciation](doc/Instanciation.md)
47+
[Instantiation / Parsing](doc/Instantiation.md)
4848

4949
[Manipulate parameters](doc/ManipulateParameters.md)
5050

5151
[Render as string](doc/RenderAsString.md)
5252

5353
## Installation
5454
PHP 7.1+ is required.
55-
> composer require bentools/querystring 1.0.x-dev
55+
> composer require bentools/querystring:^1.0
5656
5757
## Tests
5858
> ./vendor/bin/phpunit
Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Instanciation
1+
# Instantiation
22

33
You can create a `QueryString` object from a PSR-7 `UriInterface` object, a string or an array of values.
44

@@ -27,7 +27,7 @@ use BenTools\QueryString\QueryString;
2727
$qs = QueryString::factory('foo=bar&baz=bat'); // Same argument requirements
2828
```
2929

30-
## Instanciate from current location
30+
## Instantiate from current location
3131

3232
It will read `$_SERVER['QUERY_STRING']`.
3333

@@ -43,6 +43,21 @@ $qs = QueryString::createFromCurrentLocation();
4343

4444
Of course this will throw a `RuntimeException` when trying to run this from `cli` :smile:
4545

46+
## Flat query parser
47+
48+
By default, PHP considers that `?foo=bar&foo=baz` has a single parameter `foo` with value `baz`.
49+
50+
If you need to parse such query strings, you can use the `FlatParser`: multiple keys will be detected and converted to arrays.
51+
52+
```php
53+
use BenTools\QueryString\Parser\FlatParser;
54+
use function BenTools\QueryString\query_string;
55+
56+
$qs = query_string('foo=bar&foo=baz&bar=foo', new FlatParser());
57+
var_dump($qs->getParam('foo')); // array('bar', 'baz')
58+
var_dump($qs->getParam('bar')); // string 'foo'
59+
```
60+
4661
## Create your own parser
4762

4863
[bentools/querystring](https://github.com/bpolaszek/querystring) relies on PHP's `parse_str()` function to create an array of parameters from your query string.
@@ -100,4 +115,4 @@ QueryString::restoreDefaultParser();
100115
```
101116

102117

103-
[Next](ManipulateParameters.md) - Manipulate parameters
118+
[Next](ManipulateParameters.md) - Manipulate parameters

doc/ManipulateParameters.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,6 @@ Output:
127127
```
128128

129129

130-
[Previous](Instanciation.md) - Instanciation
130+
[Previous](Instantiation.md) - Instantiation
131131

132132
[Next](RenderAsString.md) - Render as string

src/Parser/FlatParser.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace BenTools\QueryString\Parser;
4+
5+
use function explode;
6+
use function is_array;
7+
use function urldecode;
8+
9+
final class FlatParser implements QueryStringParserInterface
10+
{
11+
/**
12+
* @var string
13+
*/
14+
private $separator;
15+
16+
public function __construct(string $separator = '&')
17+
{
18+
$this->separator = $separator;
19+
}
20+
21+
/**
22+
* @return array<string, mixed>
23+
*/
24+
public function parse(string $queryString): array
25+
{
26+
$params = [];
27+
$pairs = explode($this->separator, $queryString);
28+
foreach ($pairs as $pair) {
29+
if (!isset($params[$pair]) && false === strpos($pair, '=')) {
30+
$key = urldecode($pair);
31+
$params[$key] = null;
32+
continue;
33+
}
34+
[$key, $value] = explode('=', $pair);
35+
$key = urldecode($key);
36+
$value = urldecode($value);
37+
if (!isset($params[$key])) {
38+
$params[$key] = $value;
39+
} elseif (!is_array($params[$key])) {
40+
$params[$key] = [$params[$key], $value];
41+
} else {
42+
$params[$key][] = $value;
43+
}
44+
}
45+
46+
return $params;
47+
}
48+
}

tests/FlatParserTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace BenTools\QueryString\Tests;
6+
7+
use BenTools\QueryString\Parser\FlatParser;
8+
use PHPUnit\Framework\TestCase;
9+
10+
use function BenTools\QueryString\query_string;
11+
12+
class FlatParserTest extends TestCase
13+
{
14+
public function testFlatQueryParser(): void
15+
{
16+
$qs = query_string('topic=foo&topic=bar&topic=foo%20bar&foo=bar&hi', new FlatParser());
17+
$expected = [
18+
'topic' => ['foo', 'bar', 'foo bar'],
19+
'foo' => 'bar',
20+
'hi' => null,
21+
];
22+
$this->assertEquals($expected, $qs->getParams());
23+
}
24+
}

0 commit comments

Comments
 (0)