Hi
On 3/9/26 21:47, Máté Kocsis wrote:
> Same situation as above, but basically the whole section is a big question
> mark:
> I couldn't come up with a good enough idea how arrays could be handled
> efficiently and ergonomically, and in the same time, how to (mostly) conform
> to WHATWG URL.
The internal storage should not know about arrays. It should represent
things as a list of key-value pairs, with arrays only being materialized
for the methods that are intended to deal with arrays.
Given that the class is generic, matching the WHATWG API 1:1 is not
necessary in my opinion.
> Some of my problems:
> - How should $params->get("foo[bar]") behave? Should we try to parse the
> supplied key as an array and return the
> nested item if it exists? I suppose, we would internally store the query
> params as an array (just like how $_GET does),
> so then we would definitely need parsing in order to be able to return item
> "bar" stored within array "foo".
`->get()` does not currently exist within the RFC. The WHATWG `get()` is
equivalent to `->getFirst()`.
> - However, what should a $params->append("foo[bar]") call do when the query
> param "foo" is already added with a string value?
> Should it modify the existing item to be an array (but then how?) or we
> should just add "foo[bar]" to the query params as-is?
It should add `foo[bar]` as-is. `foo` and `foo[bar]` are different keys.
The square-bracket syntax is something that is specific to PHP.
> - How to recompose list parameters? Ideally, we should not append [] to
> these parameters (e.g.
The recomposition should be "dumb" and just use the keys as-is. The
complex logic should happen in the getter or setter. Only the 'array'
getters and setters deal with the PHP-specific square-bracket syntax.
To give an example:
"k=1&k=2"
[['k', '1'], ['k', '2']]
getAll('k') // ['1', '2']
getArray('k') // UriException: 'k' is not an array.
"k[]=1&k[]=2"
[['k[]', '1'], ['k[]', '2']]
getAll('k') // []
getAll('k[]') // ['1', '2']
getArray('k') // ['1', '2']
"k[a]=1&k[b]=2"
[['k[a]', '1'], ['k[b]', '2']]
getAll('k') // []
getAll('k[a]') // ['1']
getArray('k') // ['a' => '1', 'b' => '2']
"k=1&k[]=2"
[['k', '1'], ['k[]', '2']]
getAll('k') // ['1']
getAll('k[]') // ['2']
getArray('k') // UriException: 'k' is not an array.
"k[]=2&k=3";
[['k[]', '2'], ['k', '3']];
getAll('k') // ['3']
getAll('k[]') // ['2']
getArray('k') // UriException: 'k' is not an array.
The string should internally be represented something like the arrays
and the getters should work as indicated in the comment.
And then for the setters:
// []
append('k', '1') // [['k', '1']]
append('k', '2') // [['k', '1'], ['k', '2']]
append('k[]', '3') // [['k', '1'], ['k', '2'], ['k[]', '3']]
set('k', '4') // [['k[]', '3'], ['k', '4']]
The `setArray()` method would then create a number of entries with
square brackets added as appropriate (and delete all entries that would
be returned by `getArray()`). The `appendArray()` method should probably
be dropped to avoid issues with "mixing non-array with array keys". So:
// []
setArray('k', ['1']) // [['k[]', '1']]
setArray('k', ['1', '2']) // [['k[]', '1'], ['k[]', '2']]
setArray('k', ['a' => '1', '2']) // [['k[a]', '1'], ['k[0]', '2']]
append('k', 'x') // [
// ['k[a]', '1'],
// ['k[0]', '2'],
// ['k', 'x'],
// ]
setArray('k', ['1']) // [['k[]', '1']]
Does that make sense?
Best regards
Tim Düsterhus