I’m making a PHP frontend for a MySQL database. I’ve got a table called “Regions” which contains RegionID (int), Name (string), and Country (string). I’m trying to put a <select> list onto a form containing all the regions as options, using <optgroup>’s to group regions by country. I’ve already done it successfully by nested plain queries, and now I’m trying to get my head around prepared statements.
What I’ve got so far is:
// $DB is database object, already connected
// Error checking will be worked into this once I've worked out the basics...
$stmt_country = $DB->stmt_init();
$stmt_country->prepare("SELECT DISTINCT Country FROM Regions ORDER BY Country ASC");
$stmt_country->execute();
$stmt_country->bind_result($CountryName);
$stmt_region = $DB->stmt_init();
$stmt_region->prepare("SELECT RegionID,Name FROM REGIONS WHERE Country=? ORDER BY Name ASC");
$stmt_region->bind_param("s",$CountryName);
echo "<select name=\"RegionID\">\n";
while ($stmt_country->fetch()) {
// Start 'country' option group
echo "<optgroup label=\"$CountryName\">\n";
// Execute the 'regions' query using the 'country' parameter
$stmt_region->execute();
$stmt_region->bind_result($RegionID,$RegionName);
while ($stmt_region->fetch()) {
// Output the regions matching that country
echo "<option value=\"$RegionID\">$RegionName</option>\n";
}
echo "</optgroup>\n";
}
echo "</select>\n";
However when I run this I’m getting:
Warning: mysqli_stmt::bind_param(): invalid object or resource
on the $stmt_region->bind_param("s",$CountryName) line.
With some commenting out of code, I’ve got just the $stmt_country half of it working (i.e. outputs just the optgroups for each country), and then bodging in a value for $CountryName, the $stmt_region half of it works by itself, but I can’t get both halves working together. Can someone please advise where I’m going wrong?
Im pretty sure you cant have 2 staments bound on the same connection resource until after you have gone through the entire result set. Because of that your second
stmt_init()isnt actually returning a statement.It looks like all the data is on the same table so there is no need for 2 queries.
If the data were on two tables then there would still be no need for 2 queries as oyu could use a join:
What you can do, and should do even if this is not the case is use a join to get everything at once:
In either case you can get a reult set looking like:
Because of the ordering you can use a single loop comparing the previous
Countryto the current to determine when to close/open your opt group tags.