【问题标题】:php - reduce multidimensional array to query stringphp - 减少多维数组以查询字符串
【发布时间】:2014-01-10 23:01:57
【问题描述】:

今天下午我一直在寻找可行的解决方案来解决我的用例。没找到。

用例: 将数组转换为这样的格式,在 PDO 插入语句中,数组键是列,数组值是 SQL 值。如果此请求与其他请求重复,我深表歉意。我还没有找到适合我的。在我的示例中,父数组是Array[0],它被插入到一个表中,Array[1] 是孩子。它们被迭代并插入到另一个以fk_user_id 作为外键的表中。

示例插入: $sth = $dbh->prepare("INSERT INTO $table ($colData) VALUES ($valData)");

因此,列将是 (key1, key2),VALUES 将是 (:value1, :value2),依此类推。我在多维和提取子节点等方面遇到了各种问题。

样本数组:

[INFO] Array
(
    [0] => Array
        (
            [last_visit] => 1389393273.19
            [first_visit] => 1389313338.69
            [this_visit] => 1389393265.75
            [latitude] => 37.7858352661
            [longitude] => -122.406417847
            [opted_out] => 0
            [opted_in] => 0
            [user_id] => 1
            [locale] => en
            [device_maker] => unknown
            [device_model] => Simulator
            [os_platform] => iPhone OS
            [os_version] => 7.0.3
            [modified] => 1389393273.19
            [model_type] => tracker
        )
    [1] => Array
        (
            [0] => Array
                (
                    [view_count] => 1
                    [visit_timestamp] => 1389393265.63
                    [page_viewed] => home
                    [page_id] => 320
                    [fk_user_id] => 1
                    [model_type] => page
                )
            [1] => Array
                (
                    [view_count] => 2
                    [visit_timestamp] => 1389393265.64
                    [page_viewed] => contactView
                    [page_id] => 321
                    [fk_user_id] => 1
                    [model_type] => page
                )

        )
)

我尝试过的解决方案 Remove parent - keep children, Remove key from associative array, Iterating over an array, Flatten array 和其他人。我可能对代码太深了,以至于我失去了对数据的看法。我已经有一段时间没有这么多地使用 PHP 了,所以我的技能需要提高。非常感谢您的帮助。

【问题讨论】:

  • 是否有最多二维或无限数量的孩子?
  • 你考虑过json_encode吗?它不像它可能的那样紧凑,但可以满足您的目的。

标签: php mysql sql arrays pdo


【解决方案1】:

我为您准备了一个可能的解决方案,该解决方案也正在考虑通过多维数组(无限数量的孩子)。

解决方案是一个基于递归的函数,并返回一个数组,其中包含列(需要插入到数据库中)、行和包含子项的数组。

您可以遍历输出数组或静态使用其中的某些元素。 看看吧。

<?php

$arr = array(
  'key1' => 'val1',
  'key2' => 'val2',
  'key3' => 'val3',
  'key4' => array(
    'subkey1' => 'subval1',
    'subkey2' => 'subval2',    
  )
);

function walkArray($input)
{
    // Define our output array
    $output = array(
      'keys' => '',
      'vals' => '',
      'children' => array(),
    );

    // We're looping trough the input array
    foreach($input AS $key => $value)
    {
      // If the current value is an array we reached the next dimension
      if(is_array($value))
      {
        // So we call walkArray() recursively with our current value
        // and assign the returned array to a new element in our $output's 'children' key 
        $output['children'][] = walkArray($value);
      }
      else
      {
        // We'll concatenate our keys and values...
        $output['keys'] .= $key . ', '; 
        $output['vals'] .= ':' . $value .', ';
      }
    }

    // And get rid of the trailing commas
    $output['keys'] = rtrim($output['keys'], ', ');
    $output['vals'] = rtrim($output['vals'], ', ');   

    // Eventually we return our output array
    return $output; 
}

?>

<pre>
  <?php
    print_r(walkArray($arr));
  ?>
</pre>

输出将是:

Array
(
    [keys] => key1, key2, key3
    [vals] => :val1, :val2, :val3
    [children] => Array
        (
            [0] => Array
                (
                    [keys] => subkey1, subkey2
                    [vals] => :subval1, :subval2
                    [children] => Array
                        (
                        )

                )

        )

)    

【讨论】:

  • 我会测试一下。如果它对我有用,我会标记为最佳答案。谢谢,托马斯。
【解决方案2】:

从安全角度来看,以此处预期的方式将表单输入动态映射到 SQL 列是一个糟糕的想法。任何人都可以通过构造匹配的 POST 请求将任何数据转储到任何列中。

此外,通过将表单值直接插入 SQL 字符串,您很容易受到 SQL 注入的攻击。任何人都可以提交虚假的 POST 请求并执行任意 SQL,这会暴露或损坏数据库中的任何表。

给出警告后,您需要使用 PHP 的 foreach 迭代第一条记录中的键

http://www.php.net/manual/en/control-structures.foreach.php

foreach ($main_record as $column_name => $column_value) {
   ...
}

在循环内部,您必须在每次迭代中构建两个字符串。第一个包含列名(表名后面的逗号分隔列表)。第二个包含值。

之后,您必须获取最后插入记录的 ID,PDO 有一个功能。然后,您必须对每个关联记录重复此技术。

如果您想要更好的解决方案,请考虑使用 Laravel 之类的框架,其中包含一个名为 Eloquent ORM 的对象关系映射器库。它将使这类操作更简单、更安全地编程。

【讨论】:

  • 你怎么知道 OP 正在尝试将表单输入映射到数据库中?
  • 谢谢@Niels。这是一个移动应用程序的后端 php web 服务。将无法访问 URL。而且,幸运的是,我想我在发布请求后立即找到了答案。 How to insert array keys as columns
  • @ThomasDavidPlat 你是对的。这不是表单数据。
  • @Thomas David Plat - 我的错,你是对的。这是我下意识的假设。
  • 当然,在我过度设计的热情中,最简单的解决方案经常被忽略。对于 cols 和 vals:$columns = array_keys($tracks); $values = array_values($tracks); 对于准备好的语句:$query = "INSERT INTO $table (" . implode(", ", $columns) . ") VALUES ('" . implode("', '", $values) . "')"; 我将其输出到控制台并得到正确的查询。干杯!
猜你喜欢
  • 2014-12-21
  • 2018-12-13
  • 1970-01-01
  • 2014-11-15
  • 1970-01-01
  • 1970-01-01
  • 2017-07-08
  • 2014-07-16
  • 1970-01-01
相关资源
最近更新 更多