У меня проблемы с чтением массивов 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'], '{}') ));
Если у вас есть PostgreSQL 9.2, вы можете сделать что-то вроде этого:
SELECT array_to_json(pg_array_result) AS new_name FROM tbl1;
Результат вернет массив как JSON
Затем на стороне php вопрос:
$array = json_decode($returned_field);
Вы также можете конвертировать обратно. Вот страница функций JSON
Поскольку ни одно из этих решений не работает с многомерными массивами , поэтому я предлагаю здесь свое рекурсивное решение, которое работает с массивами любой сложности :
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
PS: Я знаю, что это очень старый пост, но я не смог найти решение для postgresql pre 9.2
Надежная функция для синтаксического анализа литерала массива 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 // )
Если вы можете предвидеть, какие текстовые данные вы можете ожидать в этом поле, вы можете использовать функцию array_to_string
. Он доступен в 9.1
Например, я точно знаю, что в моих полевых labes
массива никогда не будет символа '\n'
. Поэтому я преобразовываю массивы в строку с помощью функции 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###-->' );
Я попробовал ответить array_to_json, но, к сожалению, это приводит к неизвестной ошибке функции. Используя конструктор dbal query в базе данных postgres 9.2 с чем-то вроде ->addSelect('array_agg(a.name) as account_name')
, я получил в результате строку типа { "name 1", "name 2", "name 3" }
Есть только кавычки вокруг частей массива, если они содержат специальные символы, такие как пробелы или знаки препинания.
Поэтому, если есть кавычки, я делаю строку допустимой json-строкой, а затем использую встроенную функцию parse json. В противном случае я использую взрыв.
$data = str_replace(array("\r\n", "\r", "\n"), "", trim($postgresArray,'{}')); if (strpos($data, '"') === 0) { $data = '[' . $data . ']'; $result = json_decode($data); } else { $result = explode(',', $data);
}
Я вижу, что вы используете explode(',', trim($pgArray, '{}'));
Но взорваться используется для разделения строки по строке (и вы поставляете ей массив!). что-то вроде ..
$string = "A string, with, commas"; $arr = explode(',', $string);
Что вы пытаетесь сделать с массивом? если вы хотите конкатенатировать, посмотрите на implode
ИЛИ не уверены, что вы можете указать разделитель, отличный от запятой? array_to_string (anyarray, текст)
Если у вас есть контроль над запросом, который попадает в базу данных, почему бы вам просто не использовать 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);
Это оборачивает проблемы с накладными расходами и обслуживанием, которые вы понесли, пытаясь преобразовать строковое представление массива самостоятельно.