Reputation: 775
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!
Upvotes: 0
Views: 3666
Reputation: 125244
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.
Upvotes: 0
Reputation: 294
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.
Upvotes: 0
Reputation: 3895
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:
(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.
Upvotes: 1
Reputation: 61526
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.
Upvotes: 1