简体   繁体   English

如何在PHP中制作动态postgres预处理语句

[英]How to make dynamic postgres prepared statements in PHP

I'm trying to make some prepared statements in PHP using postgres. 我正在尝试使用postgres在PHP中编写一些预备语句。

It's a bit difficult to explaing so i'll just show you: 解释起来有点困难,所以我只会告诉你:

$stmt = "SELECT * FROM customer WHERE zip = '$1'";

if(isset($_POST["CITY"])){ 
   $stmt .= "AND city = '$2'";
}

if(isset($_POST["COUNTRY"])){ 
   $stmt .= "AND country = '$3'";
}

$result = pg_prepare("myconnection", "my query", $stmt);

$result1 = pg_execute("myconnection","my query", array("0000","someCity","someCountry"));

Sorry if some of the code is wrong but it's a freehand example. 对不起,如果有些代码错了,但这是一个写意的例子。 What I need is to be able to make the prepared statement dynamic depending on if some variables isset/not-null. 我需要的是能够根据某些变量isset / not-null使预准备语句动态化。 It doesn't seem to work when posting 3 variables in the array when the statement only expects 1 or if i only need to add $1 and $3 but not $2. 当语句只需要1或者我只需要添加$ 1和$ 3而不是$ 2时,在数组中发布3个变量似乎不起作用。 I hope you understand. 我希望你明白。

I need to use it this weekend, so I hope someone knows! 我需要在这个周末使用它,所以我希望有人知道!

Thank you in advance! 先感谢您!

In a prepared statement, the SQL is static on purpose. 在一份声明中,SQL是有意的静态 The number of parameters cannot vary once the statement is prepared. 一旦准备好语句,参数的数量就不会改变。

But it'd be easy for your code to submit the right number of parameters depending on the statement. 但是,根据语句,您的代码很容易提交正确数量的参数。 You could add a variable for the counter of parameters, and a dynamic php array to pass to pg_execute instead of hard-coded literals. 您可以为参数计数器添加变量,并将动态php数组传递给pg_execute而不是硬编码的文字。 And they would be incremented/populated inside the if (isset(...)) branches. 并且它们将在if (isset(...))分支内增加/填充。

There is nothing wrong in having 3 different statements (one for each case) and execute the one that applies depending on the number of parameters passed. 拥有3个不同的语句(每种情况一个)并执行适用的语句取决于传递的参数数量没有任何错误。 Example: 例:

EDIT: I modified the code to match all cases: 编辑:我修改了代码以匹配所有情况:

  • Only the zip specified 只指定了zip
  • Zip + city 邮编+城市
  • Zip + country 邮编+国家
  • Zip + city + country 邮编+城市+国家

(even if there are some other cases, you'll understand the idea) (即使有其他一些案例,你也会理解这个想法)

$stmt = "SELECT * FROM customer WHERE zip = '$1'";

if(isset($_POST["CITY"]) && isset($_POST["COUNTRY"])) { 
   $stmt3 = $stmt . " AND city = '$2'" . " AND country = '$3'";
} elseif(isset($_POST["CITY"])) { 
   $stmt1 = $stmt . " AND city = '$2'";
} elseif(isset($_POST["COUNTRY"])) {
   $stmt2 = $stmt . " AND country = '$2'";
}

if(isset($stmt3)) {
   $result = pg_prepare("myconnection", "my query", $stmt3);
   $result1 = pg_execute("myconnection","my query", array("0000","someCity","someCountry"));
} elseif(isset($stmt2)) {
   $result = pg_prepare("myconnection", "my query", $stmt2);
   $result1 = pg_execute("myconnection","my query", array("0000","someCountry"));
} elseif(isset($stmt1)) {
   $result = pg_prepare("myconnection", "my query", $stmt1);
   $result1 = pg_execute("myconnection","my query", array("0000","someCity"));
} else {
   $result = pg_prepare("myconnection", "my query", $stmt);
   $result1 = pg_execute("myconnection","my query", array("0000"));
}

I omitted (just as you did) all the error checks for brevity. 为了简洁,我省略了(正如你所做的)所有错误检查。

Although both Daniel and aymeric are correct - no sense in testing twice, nor using numbers. 虽然Daniel和aymeric都是正确的 - 测试两次,也不使用数字都没有意义。 See below: 见下文:

$some_vars = array();
$some_vars[":zip"] = $_POST["ZIP"];
$stmt = "SELECT * FROM customer WHERE zip = :zip";

if(isset($_POST["CITY"])){ 
    $some_vars[":city"] = $_POST["CITY"]);
    $stmt .= " AND city = :city";
}

if(isset($_POST["COUNTRY"])){ 
    $some_vars[":country"] = $_POST["COUNTRY"]);
    $stmt .= " AND country = :country";
}

$result = pg_prepare("myconnection", "my query", $stmt);
$result1 = pg_execute("myconnection","my query", $some_vars);

Don't forget to sanitize and such. 不要忘记消毒等。

Don't do string concatenation. 不要进行字符串连接。 Check if the parameters are set. 检查参数是否已设置。 If not set them to empty. 如果没有将它们设置为空。 Use a single query string: 使用单个查询字符串:

$zip = $_POST["zip"];
$city = $_POST["city"];
$country = $_POST["country"];

if (!isset($zip)) $zip = '';
if (!isset($city)) $city = '';
if (!isset($country)) $country = '';

$stmt = "
    select *
    from customer
    where
        (zip = '$1' or '$1' = '')
        and
        (city = '$2' or '$2' = '')
        and
        (country = '$3' or '$3' = '')
";

$result = pg_prepare("myconnection", "my query", $stmt);
$result1 = pg_execute(
        "myconnection",
        "my query",
        array($zip, $city, $country)
        );

Each condition will only be enforced if the respective parameter is not the empty string. 仅当相应参数不是空字符串时,才会强制执行每个条件。

The same logic could use the null value in stead of empty those columns contain empty strings that should be selected. 相同的逻辑可以使用null值而不是空值,这些列包含应该选择的空字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM