URI.js icon indicating copy to clipboard operation
URI.js copied to clipboard

.query() Array-Parameters won't fill PHP's $_GET as intended

Open Abromeit opened this issue 13 years ago • 8 comments

Current Version

This Code:

.query({ foo: "bar", hello: ["world", "mars"] });

Leads to this:

// -> http://example.com/bar/foo.xml?foo=bar&hello=world&hello=mars

I think that's kinda senseless. Cause this is what we see on the Server-Side:

$_GET = array(
  'foo' => 'bar',
  'hello' => 'mars'
);

I.e. "hello=world" is missing and no one can work with it.

Improved Version

Better:

// -> http://example.com/bar/foo.xml?foo=bar&hello[]=world&hello[]=mars

Results in this:

$_GET = array(
  'foo' => 'bar',
  'hello' => array(
    0 => 'world',
    1 => 'mars'
  )
);

Abromeit avatar Jun 08 '12 12:06 Abromeit

The docs contain some demo code. The last lines are

// CAUTION: beware of arrays, the following are not quite the same
// If you're dealing with PHP, you probably want the latter…
uri.search("?foo=bar&bar=baz");
uri.search("?foo=bar[]&bar[]=baz");

you get that through

uri.search({ foo: "bar", "hello[]" : ["world", "mars"] });

I cannot make URI.js inject those [] for you, as PHP is one of the few languages using this scheme. most other languages deal with this quite differently.

rodneyrehm avatar Jun 08 '12 12:06 rodneyrehm

That said, we could look into an optional "serialization callback" for query strings. Something that could convert {foo: ['bar', 'baz']} to foo[]=bar&foo[]=baz. Maybe even allow it to accept objects like {foo: {bar: 1, baz: 2}} and turn it into foo[bar]=1&foo[baz]=2.

rodneyrehm avatar Jun 08 '12 12:06 rodneyrehm

..which would be cool if we talk about a ..hm.. 'static' callback, that users have to provide only once, if they like to.

Just to let you know - I really love what you did there. Your project could reduce my node.js codebase by at least 15% or so. I'm not that bad with Regex, but there's a lot of messy stuff out there and URL-canonicalization etc. is a pain when you have to do all that stuff over and over again. Thank you so much ♥

Abromeit avatar Jun 08 '12 13:06 Abromeit

I'll look into the callbacks. It'll take me a couple of days though… heavy work load :(

To make things worse: we would also have to consider a callback for parseQuery() - something that is able to reverse whatever we plugged into buildQuery().

Thanks, for the kind words. I'm happy you like it :)

rodneyrehm avatar Jun 08 '12 13:06 rodneyrehm

Here's a first shot at URI.hooks. Just checkout the php-querystring branch and give it a go.

rodneyrehm avatar Jun 09 '12 12:06 rodneyrehm

You never got back to me with any feedback regarding the implementation. Have you had the chance to test this?

rodneyrehm avatar Aug 06 '12 09:08 rodneyrehm

Mapping from javascript-like objects to url parameters is a solved problem. It's not only PHP who relies on it (see this). Please, could you consider making use of qs for building the query string? It is standard, well-tested (used by express),... If that's not an option, you could borrow its query parsing code.

If anything else, at least provide a sane behaviour (and I'd go for the more standard-widespread one) for URI(...).query({ foo: { bar: 'whatever' }}) . Currently, it gives "?foo=%5Bobject+Object%5D", which is no good.

alex94cp avatar Aug 14 '15 02:08 alex94cp

We will find a solution that works for everyone in URI.js v2. Until then you're stuck working with qs yourself. Alternatively you can make URI.js use qs by overwriting the following functions:

var qs = require('qs');
URI.parseQuery = function(string) { return qs.parse(string); };
URI.buildQuery = function(data) { return qs.stringify(data); };

Simply popping qs into URI.js will make 39 tests fail, but most of those seem to be standard behavior that you don't want anyway, considering you explicitly asked for qs.

rodneyrehm avatar Aug 14 '15 06:08 rodneyrehm