Конвертировать массив PostgreSQL в массив PHP - PullRequest
30 голосов
/ 18 июня 2010

У меня проблемы с чтением массивов Postgresql в PHP.Я пытался взорвать (), но это разбивает массивы, содержащие запятые в строках, и 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'], '{}') ));

Ответы [ 7 ]

75 голосов
/ 02 декабря 2012

Если у вас есть PostgreSQL 9.2, вы можете сделать что-то вроде этого:

SELECT array_to_json(pg_array_result) AS new_name FROM tbl1;

Результат вернет массив в формате JSON

Тогда по вопросу php:

$array = json_decode($returned_field);

Вы также можете конвертировать обратно. Вот функции JSON страница

10 голосов
/ 15 января 2015

Поскольку ни одно из этих решений не работает с многомерными массивами , поэтому я предлагаю здесь мое рекурсивное решение, которое работает с массивами любой сложности :

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;
}

IЯ не слишком много тестировал, но, похоже, он работает.Вот мои тесты с результатами:

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

3 голосов
/ 30 сентября 2013

Надежная функция для анализа литерала массива 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
// )
1 голос
/ 04 сентября 2015

Я попробовал ответ array_to_json, но, к сожалению, это приводит к неизвестной ошибке функции.Используя построитель запросов dbal в базе данных postgres 9.2 с чем-то вроде ->addSelect('array_agg(a.name) as account_name'), я получил в результате строку типа { "name 1", "name 2", "name 3" }

. Вокруг частей массива есть только кавычки, если они содержат специальные символы, такие как пробел или пунктуация.

Поэтому, если есть кавычки, я делаю строку допустимой строкой json, а затем использую встроенную функцию синтаксического анализа 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);

}

1 голос
/ 22 марта 2014

Если вы можете предвидеть, какие текстовые данные вы можете ожидать в этом поле, вы можете использовать функцию 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###-->' );
0 голосов
/ 30 июня 2016

Если у вас есть контроль над запросом, который попадает в базу данных, почему бы вам просто не использовать 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);

Это позволяет избежать накладных расходов и проблем с обслуживанием, которые вы могли бы решить, пытаясь самостоятельно преобразовать строковое представление массива.

0 голосов
/ 18 июня 2010

Я вижу, вы используете explode(',', trim($pgArray, '{}'));

Но explode используется для разделения строки на строку (и вы предоставляете ей массив !!). что-то вроде ..

$string = "A string, with, commas";
$arr = explode(',', $string);

Что вы пытаетесь сделать с массивом? если вы хотите объединить, посмотрите на implode

ИЛИ не уверен, возможно ли для вас указать разделитель, отличный от запятой? array_to_string (anyarray, текст)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...