(PHP)我在数组中有一个未知数量的键值对,如何在sql查询中使用它们?

时间:2016-02-29 19:18:51

标签: php mysql sql arrays

我正在尝试制作库存/发票网络应用程序。用户输入诸如订单ID,日期,订单总数等信息,然后输入购买的每个产品及其各自的数量。我正在使用PDO进行SQL查询。

我事先并不知道发票中有多少独特的产品,因此我提交了一个关联数组,用于存储产品及其数量(产品名称用作密钥)。

在提交时,建立/执行准备好的声明 现在我完成了order_id,date和order_total查询。

$stmt = $connection->prepare("INSERT INTO table_1 (order_id, order_date, order_total) VALUES ('$orderid', '$date', '$total_cost')");
$stmt->execute();

那部分很简单。另一个查询的目的如下。

$testStmt = $connection->prepare("INSERT INTO table_2 (keys from the assoc array are listed here) VALUES (values from the assoc arrays are listed here)");
$testStm->execute();

一旦用户输入了一些产品,我的阵列就会看起来像这样:

$array
    (
        "product1" => quantity1
        "product2" => quantity2

    )

我到目前为止的想法是为需要包含在sql查询中的列创建一个字符串,然后为sql查询的值创建一个字符串。然后迭代遍历数组并将键和值附加到相应的字符串,以便我可以在sql查询中使用它们。我没有得到它的工作,我担心它可以打开自己注射sql(我仍然不熟悉sql注入,所以我一直在尝试阅读它。)

$columns;
$values_input;

foreach($assoc_array as $product => $quant)
{
     $columns .= "' " . $product . "', ";
     $values_input .= "' " . $quant . "', ";
}

这个想法是$ columns和$ values_input字符串最终会包含所有相应的列名和要输入这些列的数量。然后我想我可以将这些字符串用作SQL查询的一部分。这样的事情。

INSERT INTO $columns VALUES $values_input 

我很感激任何帮助或见解。如果我离开这里或者以一种迟钝的方式做某事,请随意大声说出来,如果情况确实如此,我宁愿修好一把,也不要继续。

2 个答案:

答案 0 :(得分:1)

由于您正在尝试制作库存/发票申请,您是否碰巧拥有产品数据库?如果这样做,您可能希望使用产品ID而不是产品名称作为密钥。由于产品名称听起来像是重复或可能会改变。如果产品名称发生变化,您将无法查询。

您是否接受不在数据库中的产品进入发票?如果是这样,它会增加一些复杂性。

在SQL注入中,您应该在将输入用于查询之前清理输入。阅读:What's the best method for sanitizing user input with PHP?

如果不手动查询,大多数现代框架都有许多针对SQL注入的内置保护。所以考虑使用它们。

其中许多人使用有效记录模式,请参阅:http://www.phpactiverecord.org/projects/main/wiki/Basic_CRUD(因此,您不必像处理手动编写查询一样。)

框架中活动记录的示例:https://www.codeigniter.com/user_guide/database/query_builder.html

答案 1 :(得分:1)

您已经在使用PDO,如果您想保护自己免受SQL注入,这是一件好事。你甚至试图准备你的陈述,但由于你没有约束任何参数,人们可能会争论这是否真的是你在做什么。 Example 5 on the PHP docs page实际上非常接近你想要做的事情。请允许我根据您的使用情况进行调整:

// create a placeholders string looking like "?, ?, ..., ?"
$placeholders = implode(',', array_fill(0, count($params), '?'));

// prepare the statement
$qry = $connection->prepare("INSERT INTO table_2 ($params) VALUES ($params)");

// bind the parameters to the statement. (We first need all columns, then all values)
$qry->execute(array_merge(array_keys($params), array_values($params)));

这会导致查询看起来与您的第一个示例完全相同,但具有动态数量的列或参数。由于您正在准备语句并在执行时绑定参数,因此PDO应处理所有引用和转义以防止SQL注入。

作为旁注,你的表结构对我来说似乎有点儿。我认为您没有正确地规范化您的数据,尽管使用您正在使用的表名称有点难以辨别。我相信你的结构应该看起来像这样,我担心它不会:

TABLE orders (id, date, total, client_id)
TABLE products (id, name, price, ...)
TABLE order_lines (id, order_id, product_id, quantity)
TABLE clients (...)

确切的结构显然取决于您的使用案例,但我相信,如果您想构建一个可以轻松查询的订单系统,并且可以作为可能扩展的基础,那么您可以使用最简单的结构。在将来。