Make prototype.js’s toQueryString method php safe

Posted on July 9, 2009. Filed under: JavaScript, PHP, Prototype | Tags: , , , |

LAST UPDATED APRIL 12, 2011

One hurdle I came across today is Prototype’s Hash.toQueryString() method, which turns a hash into a query string [bet you couldn’t have guessed that ;-)]. The wall I ran into was how it parses arrays within the hash, it would take something like this [in JSON]:


{"someArray": [1,2,3]}

… and run it through toQueryString(), it returns:


someArray=1&someArray=2&someArray=3

… which is incredibly useless for PHP scripts attempting to consume this query string. PHP will effectively set the String “someArray” to 1, then set it to 2, then set it to 3. Not what we expected. What we PHP devs want is this instead:


someArray[]=1&someArray[]=2&someArray[]=3

… which when consumed by PHP will set an Array called “someArray” to the values 1, 2 and 3.

Teh codes

I didn’t find a single result while trying to google this, and I doubt the prototype guys have much interest in changing this given their Ruby on Rails background [which parses the query string just fine, without the "[]"], so I wrote a quick hack to remedy this situation. Paste this at the BOTTOM of your prototype.js file:

For prototype 1.6.x:


var _toQueryStringAppendBrackets = true;
Hash.prototype.toQueryString = function() {
    function toQueryPair(key,value) {
        if (Object.isUndefined(value)) return key;
        return key + "=" + encodeURIComponent(String.interpret(value));
    }

    return this.inject([],function(results,pair) {
        var key = encodeURIComponent(pair.key), values = pair.value;

        if (values && typeof values === "object") {
            if (Object.isArray(values)) {
                key += (_toQueryStringAppendBrackets === true) ? "[]" : ""; // Uses global, dirty... I know :-)
                return results.concat(values.map(toQueryPair.curry(key)));
            }
        } else {
            results.push(toQueryPair(key,values));
        }
        return results;
    }).join("&");
}

If your using prototype 1.7, this this instead.


Hash.prototype.toQueryString = function() {
    function toQueryPair(key,value) {
        if (Object.isUndefined(value)) { return key; }
        return key + "=" + encodeURIComponent(String.interpret(value));
    }
    return this.inject([], function(results, pair) {
        var key = encodeURIComponent(pair.key), values = pair.value;
        if (values && typeof values == 'object') {
            if (Object.isArray(values)) {
                var queryValues = [],k='';
                for (var i = 0, len = values.length, value; i < len; i++) {
                    value = values[i];
                    k = key+((_toQueryStringAppendBrackets === true) ? "[]" : ""); // Uses global, dirty... I know :-)
                    queryValues.push(toQueryPair(k,value));
                }
                return results.concat(queryValues);
            }
        } else results.push(toQueryPair(key, values));
        return results;
    }).join('&');
}

I had to copy toQueryPair() into this function because it is a “private” method of Hash, and not accessible from this scope [correct me if I’m wrong]. Since toQueryString() is used internally by prototype by things like Ajax’s parameters option — and probably various other libraries written for prototype — I set the var _toQueryStringAppendBrackets to be available globally in case you need to switch this functionality on and off during script execution.

As always, if you have a more “JS ninja” way of solving this problem, please comment here and I will update this post [I’m especially turned off by having to include toQueryPair() again, and by not being able to use Object.extend() — FYI]. Any comments which are critical but not constructive will be removed. Why? Because I hate when people do that and it doesn’t make the internet better. Don’t like my rules? Don’t post anything.


Read Full Post | Make a Comment ( 1 so far )

Recently on Adventures in PHP / DHTML / CSS and MySQL…

Binding your setTimeout methods in JavaScript using Prototype

Posted on April 20, 2009. Filed under: DHTML, JavaScript | Tags: , , , , |

Memcache & MySQL PHP Session Handler

Posted on April 8, 2009. Filed under: Memcache, mysql+, PHP | Tags: , , , , |

Simple Image Resize Calculator Function

Posted on January 8, 2009. Filed under: GD, PHP |

Setting up your localhost as example.com

Posted on June 14, 2008. Filed under: Apache | Tags: , , , , , , , |

Using Memcache with MySQL and PHP

Posted on May 21, 2008. Filed under: Memcache, mysql+, PHP | Tags: , , , , , |

Use one DB connection on your custom wordpress install

Posted on May 11, 2008. Filed under: mysql+, PHP, WordPress | Tags: |

Make your website completely UTF-8 friendly

Posted on March 23, 2008. Filed under: mysql+, PHP, UTF-8 | Tags: , , , , |

Never use ORDER BY RAND() again!

Posted on March 5, 2008. Filed under: mysql+, PHP | Tags: , , , , , |

Installing memcache on Windows for PHP

Posted on January 10, 2008. Filed under: Apache, Memcache, PHP | Tags: , , , , , |

Liked it here?
Why not try sites on the blogroll...

Follow

Get every new post delivered to your Inbox.