How to make dynamic postgres prepared statements in PHP

徘徊边缘 提交于 2019-12-10 11:55:14

问题


I'm trying to make some prepared statements in PHP using postgres.

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. 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. I hope you understand.

I need to use it this weekend, so I hope someone knows!

Thank you in advance!


回答1:


In a prepared statement, the SQL is static on purpose. 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. And they would be incremented/populated inside the if (isset(...)) branches.




回答2:


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. Example:

EDIT: I modified the code to match all cases:

  • Only the zip specified
  • 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.




回答3:


Although both Daniel and aymeric are correct - no sense in testing twice, nor using numbers. 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.




回答4:


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.



来源:https://stackoverflow.com/questions/12009263/how-to-make-dynamic-postgres-prepared-statements-in-php

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!