Поскольку ни одно из других решений, кажется, не работает идеально, я получил довольно консервативный подход, состоящий из двух частей:
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']
));
}));
}
Этот метод форматирует массив в литеральную строку hstore, готовую для вставки в запрос. Это может быть немного более функционально в стиле, чем необходимо, извините за это. ^ _ ^ ;; Зависит от PHP 5.4+ и functions-php .
Чтобы получить значения hstore из Postgres, я использую JSON в качестве посредника:
SELECT array_to_json(hstore_to_array(value)) AS value ...
Получает кодированный в JSON массив, который можно превратить в обычный массив PHP, используя это:
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;
}
Это зависит от Postgres 9.2+ или 9.1 с бэкпортом json_91 .
Это скопировано прямо из некоторого пользовательского кода, не обязательно очень обобщенного, но оно уже выдержало некоторое использование в реальном мире.