【问题标题】:Convert PostgreSQL array to PHP array将 PostgreSQL 数组转换为 PHP 数组
【发布时间】:2011-03-05 08:44:51
【问题描述】:

我无法在 PHP 中读取 Postgresql 数组。我试过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'], '{}') ));

【问题讨论】:

    标签: php postgresql arrays


    【解决方案1】:

    如果你有 PostgreSQL 9.2,你可以这样做:

    SELECT array_to_json(pg_array_result) AS new_name FROM tbl1;
    

    结果将以 JSON 格式返回数组

    然后是php方面的问题:

    $array = json_decode($returned_field);
    

    您也可以转换回来。这是JSON functions页面

    【讨论】:

      【解决方案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'。所以我使用函数array_to_string将数组labes转换为字符串

          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( '<--###DELIMITER###-->', $pgLabes );
          

          【讨论】:

          • 在 php 中应该是 $phpLabels = explode( '', $pgLabes );
          • 谢谢@PawełMiłosz。修正了我的答案。
          【解决方案5】:

          正如@Kelt 提到的:

          Postgresql 数组如下所示:{1,2,3,4}

          您可以简单地将第一个 { 和最后一个 } 替换为 [ 和 ] 分别然后json_decode那个。

          但他的解决方案只适用于一维数组。

          这里是一维和多维数组的解决方案:

          $postgresArray = '{{1,2},{3,4}}';
          $phpArray = json_decode(str_replace(['{', '}'], ['[', ']'], $postgresArray));  // [[1,2],[3,4]]
          

          回退:

          $phpArray=[[1,2],[3,4]];
          $postgresArray=str_replace(['[', ']'], ['{', '}'], json_encode($phpArray));
          

          【讨论】:

            【解决方案6】:

            我尝试了 array_to_json 答案,但不幸的是,这会导致未知函数错误。 在 postgres 9.2 数据库上使用 dbal 查询构建器和 -&gt;addSelect('array_agg(a.name) as account_name') 之类的东西,我得到了类似 { "name 1", "name 2", "name 3" } 的字符串

            如果数组部分包含空格或标点符号等特殊字符,则仅在数组部分周围加上引号。

            所以如果有引号,我将字符串设为有效的 json 字符串,然后使用内置的解析 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);
            

            }

            【讨论】:

            • 你用过PostgreSQL的array_to_json()函数吗?
            【解决方案7】:

            如果您可以控制访问数据库的查询,为什么不直接使用unnest() 将结果作为行而不是 Postgres-arrays 来获取?从那里,您可以本地获取 PHP 数组。

            $result = pg_query('SELECT unnest(myArrayColumn) FROM someTable;');
            if ( $result === false ) {
                throw new Exception("Something went wrong.");
            }
            $array = pg_fetch_all($result);
            

            这避免了您尝试自己转换数组的字符串表示所带来的开销和维护问题。

            【讨论】:

              【解决方案8】:

              我可以看到你正在使用explode(',', trim($pgArray, '{}'));

              但是explode 用于逐个字符串拆分字符串(并且您正在为其提供一个数组!!)。像..

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

              你想用数组做什么?如果你想连接看看implode

              或者不确定您是否可以指定逗号以外的分隔符? array_to_string(anyarray, text)

              【讨论】:

              • 对不起,我的帖子中的代码不是很清楚。我已经对其进行了修改,以便第二个函数参数是字符串值而不是数组。请注意,PostgreSQL 的 array_to_string() 不是这种情况的解决方案,因为它会删除 NULL 和空值,这使我无法遍历数组并将值从一个数组链接到另一个数组中的关联值。
              • 为避免 NULL 问题,将它们近似为 PHP ""。使用 array_to_string(anyarray, '","'),即 SELECT '{"'|| array_to_string(anyarray, '","') || '"}' ... PHP 接收字符串 JSON $s 和$newarray = json_decode($s);
              【解决方案9】:

              Postgresql 数组如下所示:{1,2,3,4}

              您可以简单地将第一个{ 和最后一个} 分别替换为[],然后对其进行json_decode。

              $x = '{1,2,3,4}';
              $y = json_decode('[' . substr($x, 1, -1) . ']');  // [1, 2, 3, 4]
              

              反之亦然:

              $y = [1, 2, 3, 4];
              $x = '{' . substr(json_encode($y), 1, -1) . '}';
              

              【讨论】:

                【解决方案10】:

                根据线程中的答案,我创建了两个可以使用的简单 php 函数:

                private function pgArray_decode(string $pgArray){
                    return explode(',', trim($pgArray, '{}'));
                }
                
                private function pgArray_encode(array $array){
                    $jsonArray = json_encode($array, true);
                    $jsonArray = str_replace('[','{',$jsonArray);
                    $jsonArray = str_replace(']','}',$jsonArray);
                    return $jsonArray;
                }
                

                【讨论】:

                  【解决方案11】:

                  一个简单快速的函数,无需使用 pg 连接即可将深度 PostgreSQL 数组字符串转换为 JSON 字符串。

                  function pgToArray(string $subject) : array
                  {
                      if ($subject === '{}') {
                         return array();
                      }
                      $matches = null;
                      // find all elements; 
                      // quoted: {"1{\"23\"},abc"} 
                      // unquoted: {abc,123.5,TRUE,true} 
                      // and empty elements {,,}
                      preg_match_all( '/\"((?<=\\\\).|[^\"])*\"|[^,{}]+|(?={[,}])|(?=,[,}])/', $subject,$matches,PREG_OFFSET_CAPTURE);
                      $subject = str_replace(["{","}"],["[","]"],$subject); // converting delimiters to JSON
                      $matches = array_reverse($matches[0]);
                      foreach ($matches as $match) {
                          $item = trim($match[0]);
                          $replace = null;
                          if ((strpos($item,"{") !== false) || (strpos($item,"}") !== false)) {
                              // restoring replaced '{' and '}' inside string
                              $replace = $match[0];
                           } elseif (in_array($item,["NULL","TRUE","FALSE"])) {
                              $replace = strtolower($item);
                           } elseif ($item === "" || ($item[0] !== '"' && !in_array($item,["null","true","false"]) && !is_float($item))) {
                              $replace = '"' . $item . '"'; // adding quotes to string element
                           }
                           if ($replace) { // concatenate modified element instead of old element
                              $subject = substr($subject, 0, $match[1]) . $replace . substr($subject, $match[1] + strlen($match[0]));
                           }
                       }
                       return json_decode($subject, true);
                    }
                  

                  【讨论】:

                    猜你喜欢
                    • 2020-09-04
                    • 2015-12-29
                    • 2017-09-03
                    • 2018-12-16
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多