Since none of the other solutions seem to be working perfectly, I ended up with a rather conservative two-part approach:
protected function toPostgresHStoreLiteral(array $array) {
return join(',', F\map($array, function ($value, $key) {
switch (strtolower(gettype($value))) {
case 'null' :
case 'boolean' :
$value = $value ? 'true' : '';
break;
case 'object' :
if (!is_callable([$value, '__toString'])) {
throw new \InvalidArgumentException(sprintf('Cannot cast object of type %s to string', get_class($value)));
}
// deliberate fallthrough
case 'integer' :
case 'double' :
case 'string' :
settype($value, 'string');
break;
default :
throw new \InvalidArgumentException(sprintf('Cannot store values of type %s in an hstore', gettype($value)));
}
return call_user_func_array('sprintf', array_reduce(
[$key, $value],
function (array $args, $value) { return array_merge($args, [sprintf('"%s"', addcslashes($value, '"\\'))]); },
['%s=>%s']
));
}));
}
This method formats an array into an hstore literal string ready to be inserted into a query. It may be a little more functional in style than necessary, sorry for that. ^_^;; Depends on PHP 5.4+ and functional-php.
To get hstore values out of Postgres, I'm using JSON as the middle man:
SELECT array_to_json(hstore_to_array(value)) AS value ...
This gets a JSON encoded array which can be turned into a regular PHP array using this:
protected function postgresJsonHstoreToArray($json) {
$values = json_decode($json, true);
$array = [];
for ($i = 0, $length = count($values); $i < $length; $i++) {
$key = $values[$i];
$value = $values[++$i];
$array[$key] = $value;
}
return $array;
}
This depends on Postgres 9.2+ or 9.1 with the json_91 backport.
This is copied straight out of some custom code, not necessarily very generalized, but it has withstood some realworld usage already.