简体   繁体   中英

How to make dynamic postgres prepared statements in PHP

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!

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.

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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