Why is my PHP nested while loop not working? - php

I was trying to fetch some data from mysql using PDO. For example, there is one table for brand names like Mercedes, Audi, Bently, Toyota. And there is another table for car names of each brand. The id s from the 'brand' tables are the foreign keys in the 'cars' table. Now I want to fetch all car names inside each brand name. Here is my code :
// Outer loop for Brands
$query = "SELECT * FROM brand";
$result = $db->query($query);
while($row=$result->fetch(PDO::FETCH_OBJ)){
$brand_name = $row->brand_name;
$brand_id = $row->id;
echo $brand_name;
echo "<br>";
// Inner loop for Cars
$query = "SELECT * FROM cars WHERE brand_id = $brand_id";
$result = $db->query($query);
while($row=$result->fetch(PDO::FETCH_OBJ)){
$car_name = $row->car_name;
echo $car_name;
echo "<br>";
} // Ending of inner loop
} // Ending of outer loop
But I got a problem here. The first brand name is fetched and then the inner loop runs and fetched the car names inside that brand. When the inner loop finished fetching all car names it should go to the outer loop again and find the next brand name. But it is not fetching the rest of the brand names and the car names as well. For example, if it finishes fetching all car names inside Toyota it doesn't go for the next brand name which is Audi.
But if I remove the inner while loop it fetched all the brand names without any errors. Please help me out with your best possible solutions. Thanks in advance.

Try use different var name otherwise you overwrite le first vars
eg $sql, $result and $row and in second $sql2, $result2, $row2
$query = "SELECT * FROM brand";
$result = $db->query($query);
while($row=$result->fetch(PDO::FETCH_OBJ)){
$brand_name = $row->brand_name;
$brand_id = $row->id;
echo $brand_name;
echo "<br>";
// Inner loop for Cars
$query2 = "SELECT * FROM cars WHERE brand_id = $brand_id";
$result2 = $db->query($query2);
while($row2=$result2->fetch(PDO::FETCH_OBJ)){
$car_name = $row2->car_name;
echo $car_name;
echo "<br>";
} // Ending of inner loop
} // Ending of outer loop

You need to change variable names of your inner loop.
Right now you are overriding values of your outer loop in your inner loop (result and row).
// Loop for Brands
$query = "SELECT * FROM brand";
$result = $db->query($query);
while($row=$result->fetch(PDO::FETCH_OBJ)){
$brand_name = $row->brand_name;
$brand_id = $row->id;
echo $brand_name;
echo "<br>";
// Loop for Cars
$query = "SELECT * FROM cars WHERE brand_id = $brand_id";
$result = $db->query($query);
while($row=$result->fetch(PDO::FETCH_OBJ)){
$car_name = $row->car_name;
echo $car_name;
echo "<br>";
} // Ending of inner loop
} // Ending of outer loop
Use bindParam that PDO offers in PHP for setting variables https://www.php.net/manual/en/pdostatement.bindparam.php

Just change the variable names $query,$row and $result for the inner query and everything will work fine.
Your result of the first query held in $result is getting overwritten by the result of inner query
// Outer loop for Brands
$query = "SELECT * FROM brand";
$result = $db->query($query);
while($row=$result->fetch(PDO::FETCH_OBJ)){
$brand_name = $row->brand_name;
$brand_id = $row->id;
echo $brand_name;
echo "<br>";
// Inner loop for Cars
$query1 = "SELECT * FROM cars WHERE brand_id = $brand_id";
$result1 = $db->query($query1);
while($row1=$result1->fetch(PDO::FETCH_OBJ)){
$car_name = $row1->car_name;
echo $car_name;
echo "<br>";
} // Ending of inner loop
}

Your variable names override each other and you should rename them
and also consider using closeCursor() to release resources.
Applying above would look like below:
// Loop for Brands
$sql = "SELECT * FROM brand";
$brandQuery = $db->query($sql);
while ($brandRow = $brandQuery->fetch(PDO::FETCH_OBJ))
{
$brand_name = $brandRow->brand_name;
$brand_id = $brandRow->id;
echo $brand_name;
echo "<br>";
// Loop for Cars
$sql = "SELECT * FROM cars WHERE brand_id = $brand_id";
$carQuery = $db->query($sql);
while ($carRow = $carQuery->fetch(PDO::FETCH_OBJ))
{
$car_name = $carRow->car_name;
echo $car_name;
echo "<br>";
} // Ending of inner loop
$carQuery->closeCursor();
} // Ending of outer loop
$brandQuery->closeCursor();

Related

nested loop but avoiding the repetition of first loop

I have two tables; One is category and the other one is sub_category.
First I want to display all the items in category and store the value of each category and then display all the sub_categories related to that category but the category should not repeat (it should be displayed only once for all sub-categories).
.
<?php
$abcd = $mysqli->query("SELECT * FROM categories;");
while($obj = $abcd->fetch_object())
{
$category = $obj->name;
$results = $mysqli->query("SELECT * FROM `sub-category` WHERE category = '$category';");
while($omg=$results->fetch_object())
{
echo $category. ' '.$omg->subcategory.'<br>';
}
echo $omg->subcategory;
}
?>
Create an array of subcats and implode them so you only get commas where you want them. Only print the $category outside the loop.
<?php
$abcd = $mysqli->query("SELECT * FROM categories ");
while ($obj = $abcd->fetch_object()) {
$category = $obj->name;
$results = $mysqli->query("SELECT * FROM `sub-category` WHERE category = '$category' ");
echo $category.': ';
$subcats = array();
while ($omg = $results->fetch_object()) {
$subcats[] = $omg->subcategory;
}
echo implode(',', $subcats).'<br>';
}
?>
Use a simple JOIN.
<?php
$abcd = $mysqli->query('SELECT DISTINCT categories.name,sub-category.subcategory FROM `categories` JOIN `sub-category` ON category.name = categories.category;');
while($obj = $abcd->fetch_object())
{
echo $obj->name.' '.$obj->subcategory.'<br>';
}
?>

How to Get another value in another table using a dynamic call

I currently have this query with an array that outputs the variables within using a dynamic input in my form (term), this creates a Dynamic Search with auto complete to fill in all of the details for a product.
$return_arr = array();
$param = $_GET["term"];
$fetch = mysql_query("SELECT * FROM crd_jshopping_products WHERE `name_en-GB` REGEXP '^$param'");
while ($row = mysql_fetch_array($fetch, MYSQL_ASSOC)) {
//$row_array['category_id'] = $row ['category_id'];
$row_array['product_id'] = $row['product_id'];
$row_array['product_names'] = $row['name_en-GB'];
$row_array['jshop_code_prod'] = $row['product_ean'];
$row_array['_ext_price_html'] = number_format($row['product_price'],2);
if (!empty($row['product_thumb_image']) AND isset($row['product_thumb_image'])){
$row_array['image'] = $row['product_thumb_image'];
}else {
$row_array['image'] = 'noimage.gif';
}
array_push( $return_arr, $row_array);
}
mysql_close($conn);
echo json_encode($return_arr);
Unfortunately I also need to get the category_id which is not in the same table, I have tried to modify my query as such, but to no avail:
$fetch = mysql_query("SELECT * FROM crd_jshopping_products WHERE `name_en-GB` REGEXP '^$param' AND `crd_jshopping_products_to_categories` = `product_id` ");
What step am I missing here ? The product_id's match in both tables?
try this query instead and try to understand what I have written in it:
$fetch = mysql_query("
SELECT
p.*,
c.category_id
FROM
crd_jshopping_products as p
INNER JOIN crd_jshopping_products_to_categories as c
ON p.product_id = c.product_id
WHERE
`p.name_en-GB` REGEXP '^$param'
");
This means:
SELECT:
Give me everything from p and the category_id from c.
FROM:
Do this from rows in the tables crd_jshopping_products (referred to as p) and crd_jshopping_products_to_categories (referred to as c), where the rows match on the count of p.product_id is the same as c.product_id.
WHERE:
Only return the rows where p.name_en-GB REGEXP '^$param'.

some problems with in_array function

Hi I am trying to use in_array, I think my syntax is correct,
but it says "Wrong datatype for second argument"
My code is
$result = mysqli_query($con, "SELECT * FROM Products WHERE Quantity_On_Hand < Min_Stock");
$filter = mysqli_query($con, "SELECT ProductID FROM Orders");
while($row = mysqli_fetch_array($result))
{
if (in_array($row['ProductID'], $filter))
{
}
}
My idea is to find out if the ProductID from Products Table is in the Order Table.
Could someone helps me, Thanks :-)
$filter isn't an array; it's a mysqli_result object:
$filter = mysqli_query($con, "SELECT ProductID FROM Orders");
I think you want to iterate over that, add each ProductID to a new array, and then pass that array to the in_array function like so:
$filter = mysqli_query($con, "SELECT ProductID FROM Orders");
$product_ids = array();
while ($row = $filter->fetch_assoc())
{
$product_ids[] = $row['ProductID'];
}
$result = mysqli_query($con, "SELECT * FROM Products WHERE Quantity_On_Hand < Min_Stock");
while($row = mysqli_fetch_array($result))
{
if (in_array($row['ProductID'], $product_ids))
{
}
}
Your code is failing because $filter is a MySQLi result resource, not an array. Really, this is better accomplished with a simple inner join between the two tables. If a ProductID does not exist in Orders, the INNER JOIN will exclude it from the result set in the first place.
$sql = "
SELECT Products.*
FROM
Products
INNER JOIN Orders ON Products.ProductID = Orders.ProductID
WHERE Quantity_on_Hand < Min_stock";
$result = mysqli_query($con, $sql);
if ($result) {
$results = array();
while ($row = mysqli_fetch_array($result)) {
$results[] = $row;
}
}
// Now $results is a 2D array of all your Products
If instead you want to retrieve all the Products, and simply have an indication of whether it has an active order, use a LEFT JOIN and test if Orders.ProductID is null in the SELECT list:
$sql = "
SELECT
Products.* ,
/* No orders will print 'no-orders' in a pseudo column called has_orders */
CASE WHEN Orders.ProductID IS NULL THEN 'no-orders' ELSE 'has-orders' AS has_orders
FROM
Products
LEFT JOIN Orders ON Products.ProductID = Orders.ProductID
WHERE Quantity_on_Hand < Min_stock";
$result = mysqli_query($con, $sql);
if ($result) {
$results = array();
while ($row = mysqli_fetch_array($result)) {
$results[] = $row;
}
}
// Now $results is a 2D array of all your Products
// And the column $row['has_orders'] will tell you if it has any...
In this case, you may test in a loop over your rowset whether it has orders:
foreach ($results as $r) {
if ($r['has_orders'] == 'has-orders') {
// this has orders
}
else {
// it doesn't...
}
}

PDO multiple SELECT statements

How can i do multiple select statements in one file? For example i have a list of products - i then want to get the stock level's for each of the products. However, it only ever returns the first product, not any other additional products.
$query = $db->query("SELECT * FROM `products` ORDER BY `productName` ASC");
while ($row = $query->fetch(PDO::FETCH_ASSOC)){
$productId = stripslashes($row['productId']);
$productName = stripslashes($row['productName']);
echo "<b>".$productName."</b><br />";
$query = $db->query("SELECT * FROM `stock` WHERE `productId` = $productId");
while ($row = $query->fetch(PDO::FETCH_ASSOC)){
$stockId = stripslashes($row['stockId']);
$stockFilename = stripslashes($row['stockFilename']);
}
echo "Stock level= " . $query-> rowCount();
}
Because your second $query is overwriting the first. Rename the second to $query2 (and change the the $query variables to $query2 beneath it). And change $row to $row2
By the way, you can also change your first query into a join to eliminate the second query alltogether.

how can i controll while loop into another while loop

Suppose I have a while loop like:
$sql = mysql_query("SELECT * FROM tablename");
while($row = mysql_fetch_array($sql)){
$id = $row["id"];
$sql_2 = mysql_query("SELECT * FROM secondtable WHERE id != $id ");
while($ro = mysql_fetch_array($sql_2)){
$id2 = $ro["id2"];
echo $id2;
}
}
then if first query return 5 results i.e 1-5 and second query returns 3 results than if i want to echo out second query it gives me like this..........
111112222233333
than how can i fix to 123 so that the second while loop should execute according to number of times allowed by me........!! how can i do that.........!!
I'm not sure I 100% understand your question - it's a little unclear.
It's possible you could solve this in the query with a GROUP BY clause
$sql_2 = mysql_query("SELECT id FROM secondtable WHERE id != $id GROUP BY id");
But that would only work if you need just secondtable.id and not any of the other columns.
When you say "number of time allowed by me" do you mean some sort of arbitrary value? If so, then you need to use a different loop mechanism, such as Greg B's solution.
Do you want to explicitly limit the number of iterations of the inner loop?
Have you considered using a for loop?
$sql = mysql_query("SELECT * FROM tablename");
while($row = mysql_fetch_array($sql)){
$id = $row["id"];
$sql_2 = mysql_query("SELECT * FROM secondtable WHERE id != $id ");
for($i=0; $i<3; $i++){
$ro = mysql_fetch_array($sql_2);
$id2 = $ro["id2"];
echo $id2;
}
}
Your first while loop is iterating over all 5 results, one at a time.
Your second while loop is iterating over each of the 5 results, producing it's own set of results (i.e. 3 results for each of the 5 iterations, totaling 15 results).
I believe what you are trying to do is exclude all IDs found in your first loop from your second query. You could do that as follows:
$sql = mysql_query("SELECT * FROM tablename");
$exclude = array();
while($row = mysql_fetch_array($sql)) {
array_push($exclude, $row['id']);
}
// simplify query if no results found
$where = '';
if (!empty($exclude)) {
$where = sprintf(' WHERE id NOT IN (%s)', implode(',', $exclude));
}
$sql = sprintf('SELECT * FROM secondtable%s', $where);
while($row = mysql_fetch_array($sql_2)) {
$id2 = $row["id2"];
echo $id2;
}
$sql = mysql_query("SELECT * FROM tablename");
$tmp = array();
while($row = mysql_fetch_array($sql)){
$id = $row["id"];
if(!in_array($id, $tmp)) {
$sql_2 = mysql_query("SELECT * FROM secondtable WHERE id != $id ");
while($ro = mysql_fetch_array($sql_2)){
$id2 = $ro["id2"];
echo $id2;
}
$tmp[] = $id;
}
}
Saving all queried $id's in an array to check on the next iteration if it has already been queried. I also think that GROUPing the first query result would be a better way.
I agree with Leonardo Herrera that it's really not clear what you're trying to ask here. It would help if you could rewrite your question. It sounds a bit like you're trying to query one table and not include id's found in another table. You might try something like:
SELECT * FROM secondtable t2
WHERE NOT EXISTS (SELECT 1 FROM tablename t1 WHERE t1.id = t2.id);

Categories