Преобразование массива PostgreSQL в массив PHP
У меня проблемы с чтением массивов Postgresql в PHP. Я попробовал explode(), но это разбивает массивы, содержащие запятые в строках, и str_getcsv(), но также не так хорошо, как PostgreSQL не цитирует японские строки.
Не работает:
explode(',', trim($pgArray['key'], '{}'));
str_getcsv( trim($pgArray['key'], '{}') );
Пример:
// print_r() on PostgreSQL returned data: Array ( [strings] => {または, "some string without a comma", "a string, with a comma"} )
// Output: Array ( [0] => または [1] => "some string without a comma" [2] => "a string [3] => with a comma" )
explode(',', trim($pgArray['strings'], '{}'));
// Output: Array ( [0] => [1] => some string without a comma [2] => a string, with a comma )
print_r(str_getcsv( trim($pgArray['strings'], '{}') ));
Ответы
Ответ 1
Если у вас есть PostgreSQL 9.2, вы можете сделать что-то вроде этого:
SELECT array_to_json(pg_array_result) AS new_name FROM tbl1;
Результат вернет массив как JSON
Затем на стороне php:
$array = json_decode($returned_field);
Вы также можете конвертировать назад. Вот функции JSON страница
Ответ 2
Поскольку ни одно из этих решений не работает с многомерными массивами, поэтому я предлагаю здесь свое рекурсивное решение, которое работает с массивами любой сложности:
function pg_array_parse($s, $start = 0, &$end = null)
{
if (empty($s) || $s[0] != '{') return null;
$return = array();
$string = false;
$quote='';
$len = strlen($s);
$v = '';
for ($i = $start + 1; $i < $len; $i++) {
$ch = $s[$i];
if (!$string && $ch == '}') {
if ($v !== '' || !empty($return)) {
$return[] = $v;
}
$end = $i;
break;
} elseif (!$string && $ch == '{') {
$v = pg_array_parse($s, $i, $i);
} elseif (!$string && $ch == ','){
$return[] = $v;
$v = '';
} elseif (!$string && ($ch == '"' || $ch == "'")) {
$string = true;
$quote = $ch;
} elseif ($string && $ch == $quote && $s[$i - 1] == "\\") {
$v = substr($v, 0, -1) . $ch;
} elseif ($string && $ch == $quote && $s[$i - 1] != "\\") {
$string = false;
} else {
$v .= $ch;
}
}
return $return;
}
Я не тестировал его слишком много, но похоже, что он работает.
Здесь у вас есть мои тесты с результатами:
var_export(pg_array_parse('{1,2,3,4,5}'));echo "\n";
/*
array (
0 => '1',
1 => '2',
2 => '3',
3 => '4',
4 => '5',
)
*/
var_export(pg_array_parse('{{1,2},{3,4},{5}}'));echo "\n";
/*
array (
0 =>
array (
0 => '1',
1 => '2',
),
1 =>
array (
0 => '3',
1 => '4',
),
2 =>
array (
0 => '5',
),
)
*/
var_export(pg_array_parse('{dfasdf,"qw,,e{q\"we",\'qrer\'}'));echo "\n";
/*
array (
0 => 'dfasdf',
1 => 'qw,,e{q"we',
2 => 'qrer',
)
*/
var_export(pg_array_parse('{,}'));echo "\n";
/*
array (
0 => '',
1 => '',
)
*/
var_export(pg_array_parse('{}'));echo "\n";
/*
array (
)
*/
var_export(pg_array_parse(null));echo "\n";
// NULL
var_export(pg_array_parse(''));echo "\n";
// NULL
P.S.: Я знаю, что это очень старый пост, но я не мог найти решение для postgresql pre 9.2
Ответ 3
Надежная функция для синтаксического анализа литерала массива PostgreSQL (одномерного) в массив PHP с использованием регулярных выражений:
function pg_array_parse($literal)
{
if ($literal == '') return;
preg_match_all('/(?<=^\{|,)(([^,"{]*)|\s*"((?:[^"\\\\]|\\\\(?:.|[0-9]+|x[0-9a-f]+))*)"\s*)(,|(?<!^\{)(?=\}$))/i', $literal, $matches, PREG_SET_ORDER);
$values = [];
foreach ($matches as $match) {
$values[] = $match[3] != '' ? stripcslashes($match[3]) : (strtolower($match[2]) == 'null' ? null : $match[2]);
}
return $values;
}
print_r(pg_array_parse('{blah,blah blah,123,,"blah \\"\\\\ ,{\100\x40\t\daő\ő",NULL}'));
// Array
// (
// [0] => blah
// [1] => blah blah
// [2] => 123
// [3] =>
// [4] => blah "\ ,{@@ daőő
// [5] =>
// )
var_dump(pg_array_parse('{,}'));
// array(2) {
// [0] =>
// string(0) ""
// [1] =>
// string(0) ""
// }
print_r(pg_array_parse('{}'));
var_dump(pg_array_parse(null));
var_dump(pg_array_parse(''));
// Array
// (
// )
// NULL
// NULL
print_r(pg_array_parse('{または, "some string without a comma", "a string, with a comma"}'));
// Array
// (
// [0] => または
// [1] => some string without a comma
// [2] => a string, with a comma
// )
Ответ 4
Если вы можете предвидеть, какие текстовые данные вы можете ожидать в этом поле, вы можете использовать функцию array_to_string
. Он доступен в 9.1
например. Я точно знаю, что у моего массива labes
никогда не будет символа '\n'
. Поэтому я преобразовываю массив labes
в строку с помощью функции array_to_string
SELECT
...
array_to_string( labels, chr(10) ) as labes
FROM
...
Теперь я могу разбить эту строку с помощью функции PHP explode
:
$phpLabels = explode( $pgLabes, "\n" );
Вы можете использовать любую последовательность символов для разделения элементов массива.
SQL:
SELECT
array_to_string( labels, '<--###DELIMITER###-->' ) as labes
PHP:
$phpLabels = explode( $pgLabes, '<--###DELIMITER###-->' );
Ответ 5
Я попробовал ответить array_to_json, но, к сожалению, это приводит к неизвестной ошибке функции.
Используя dbal query builder в базе данных postgres 9.2 с чем-то вроде ->addSelect('array_agg(a.name) as account_name')
, я получил в результате строку типа { "name 1", "name 2", "name 3" }
Есть только кавычки вокруг частей массива, если они содержат специальные символы, такие как пробелы или знаки препинания.
Итак, если есть кавычки, я делаю строку допустимой строкой json, а затем использую встроенную функцию parse json. В противном случае я использую explode.
$data = str_replace(array("\r\n", "\r", "\n"), "", trim($postgresArray,'{}'));
if (strpos($data, '"') === 0) {
$data = '[' . $data . ']';
$result = json_decode($data);
} else {
$result = explode(',', $data);
}
Ответ 6
Я вижу, что вы используете explode(',', trim($pgArray, '{}'));
Но explode используется для разделения строки по строке (и вы поставляете ей массив!!). что-то вроде..
$string = "A string, with, commas";
$arr = explode(',', $string);
Что вы пытаетесь сделать с массивом? если вы хотите конкатенировать, посмотрите implode
ИЛИ не уверен, что вы можете указать разделитель, отличный от запятой? array_to_string (anyarray, текст)
Ответ 7
Если у вас есть контроль над запросом, который попадает в базу данных, почему бы вам просто не использовать unnest()
, чтобы получить результаты в виде строк вместо массивов Postgres? Оттуда вы можете получить PHP-массив.
$result = pg_query('SELECT unnest(myArrayColumn) FROM someTable;');
if ( $result === false ) {
throw new Exception("Something went wrong.");
}
$array = pg_fetch_all($result);
Это обойдутся проблемами служебных и служебных программ, которые вы понесли, пытаясь самостоятельно преобразовать представление строки массива.