Use PDO statement multiple times when using multiple foreach loops - php

I have the following code:
if(!empty($postCountryAdd)) {
$sqlQueryLocalityAdd = $dbh->prepare("SELECT DISTINCT locality_add FROM table WHERE country_add = :country_add ORDER BY locality_add ASC");
$sqlQueryLocalityAdd->execute(array(':country_add' => $postCountryAdd));
echo '<option value="">Select locality</option>';
foreach($sqlQueryLocalityAdd as $localityAddRow) {
//while ($localityAddRow = $sqlQueryLocalityAdd->fetch()){
echo '<option value="';
echo $localityAddRow["locality_add"];
echo '">';
echo $localityAddRow["locality_add"];
echo '</option>';
}
}
If I use foreach($sqlQueryLocalityAdd as $localityAddRow) the code stops responding. Why can't I use foreach more than once? How can I fix it please?

$sqlQueryLocalityAdd is an Object which in this case - which I am showing and OP has used - cannot be iterated through. (bold so #deceze can understand).
You can use the fetchAll() inside a foreach loop to achieve this however.
Your code should look something like this:
[...]
if($sqlQueryLocalityAdd->execute(array(':country_add' => $postCountryAdd)):
foreach($sqlQueryLocalityAdd->fetchAll() as $row):
echo $row['column'];
[...]
endforeach;
endif;
[...]
Difference between an array and an Object

The problem is that the result set can only be iterated once; it is then exhausted, MySQL discards it, and you cannot iterate it again.
I have never actually tried this, but to create a result set which can be iterated several times, you need a scrollable cursor, which you should be able to create thusly:
$sqlQueryLocalityAdd = $dbh->prepare(..., [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
You should then theoretically be able to iterate the result multiple times.
If that doesn't work, fetch the data into an array using $sqlQueryLocalityAdd->fetchAll() and iterate it as often as you want. In fact, that appears to be the only option with MySQL: https://stackoverflow.com/a/19076778/476

$sqlQueryLocalityAdd isn't a result set, it's a PDOStatement object and you can only iterate over it directly once (as noted clearly by deceze).
The execute() statement returns a boolean true or false on success of the query.
If successfully run, you need to fetch results from it post-query and iterate the array returned:
$success = $sqlQueryLocalityAdd->execute(array(':country_add' => $postCountryAdd));
if($success) {
$results = $sqlQueryLocalityAdd->fetchAll();
foreach($results as $localityAddRow) {
echo '<option value="';
....
The resulting array $results is just a vanilla array, so you can iterate over it as many times as you want.
Note: If the execute() returns false, something is wrong with the query--a successful running query returning a empty result set results will still result in a true.

Related

How to get each value in a column of database in php

I don't have enough knowledge about this criteria:
I want to loop inside the for each loop to get all values in a particular column.
For example: I got the values from DB through get_result and store the result in $results.
After that use:
for each($results as $result)
❴
$output = $result->message
❵
Where message is a column in DB.
I want to loop over all the messages instead of storing last one by replacing.
Can you please give me suggestions on how to loop inside for each?
Try this:
$output[] = $result ->message;
Now $output will contain all messages on index 0, 1, 2 ...
You are facing the issue because:
$output=$result ->message;
the above line is present inside the loop, and each new iteration onerride the old value.
Well if you just looking for foreach inside foreach then you can try the following.
<?php
foreach($results as $result){
$output=$result->message;
foreach($output as $messages){
echo $messages;
}
}
?>
You don't need to put the message into another variable. You can do whatever you need to do inside the loop. For example, if you are displaying the messages, you can get it done inside the loop:
foreach ($results AS $result) {
echo $results->message . "<br>";
}

"Properly" looping through (my)SQL response

I have a class that does the MySQL stuff for me.
I have 1 to n rows in a MySQL Table and want to query specific results.
To query a table, I can now use
$db->select('tablename', '*');
$res = $db->Result()
to get the results as an associative array.
Now if I want to loop through, I have to check if there is one or more results and then either display that one result or loop through the results.
This bloats up my code and I would like to find a way to combine both results.
At the moment, I am doing this stuff like so:
if(is_array($res[0]){
//we have more than one result
foreach($res as $something)
{
//do stuff here
}
}
else
{
//do the same stuff as above here but now with other variables since $something is only filled in the foreach loop
}
Now as said, I would love to combine those two and have only one piece of code to display the results (or work further with them)
Change the input data structure into the format the loop expects, then iterate through it in the loop:
if(!is_array($res[0]){
$res[0] = [$res[0]];
}
foreach($res as $something)
{
//do stuff here
}
I would suggest you to switch to some wide deveoped classes like PDO (http://php.net/manual/en/book.pdo.php) or simply add a check in your Result method that returns an empty array in cases there are no results
function Result() {
// stuff to fetch and fill $arr;
return (is_array($arr[0])) $arr : array();
}

Select only arrays for foreach

I've got a foreach statement that on an item that has both objects and arrays in it.
foreach($result as $data)
that contains both arrays and objects. how do i specify the foreach to only select to loop through one or the other? when it loops through them all it takes forever
I had tried foreach($result->data as $data) but then it errors on the arrays telling me it is trying to get property of an object, which is understandable. once I add an if statement to check if the first result is an object it almost triples the script run time since there are so many results.
Well you could just use is_object() and is_array() (both return a boolean):
if (is_object($var)) {
// do something
} else if (is_array($var)) {
// well then, do something else
}

PHP While loop only echoes once

this is the PHP code i have:
while($row1 = mysql_fetch_object($query1)) {
echo "*".$row1->id."*";
while ($row2 = mysql_fetch_object($query2)) {
echo "%".$row2->id."%";
}
}
I want it to output for example: *1*%1%%2%%3%%4%*2*%1%%2%%3%%4%*3*%1%%2%%3%%4%
But what this loop outputs is: *1*%1%%2%%3%%4%*2**3*
(It only outputs the $row2 values in the first loop of $row1.
How can I fix this? Thanks.
A few things to note about mysql_fetch_object(). From the PHP document:
Warning: This extension is deprecated as of PHP 5.5.0
Please note above.
returns an object with properties that correspond to the fetched row and moves the internal data pointer ahead.
Please note what I bolded.
The $result object (in your code this would be $query2) is an iterative object that has a pointer pointing to the current item.
Current Item
|
v
[1][2][3][4]
When your first loop hits your second loop, it iterates over the whole thing, such that at the end, the object now looks something like this:
Current Item
|
v
[1][2][3][4]
For each iteration of the first loop, after the first time, the mysql_fetch_object() function basically goes like this:
mysql_fetch_object() ~
1. Get the next time
2. Uh, there are no more objects because we're at item [4]. Return done.
So, how do you get it to work? You could simply save the results into an array and then iterate over that array or you can reset the pointer with mysql_data_seek() (which is also deprecated as of 5.5).
To reset the data pointer, it would be something like this:
while($row1 = mysql_fetch_object($query1)) {
echo "*".$row1->id."*";
while ($row2 = mysql_fetch_object($query2)) {
echo "%".$row2->id."%";
}
// put the result pointer back to the front
mysql_data_seek($query2, 0)
}
Note1, This SO question/answer helped me find the function to use to reset the pointer.
Note, the downside is that you're calling a function that's creating an object, which creates processing overhead every time it runs.
The other option would be save the results into an array and just loop through the array every time:
$secondary_result = array();
while ($row2 = mysql_fetch_object($query2)) {
$secondary_result[] = $row2;
}
while($row1 = mysql_fetch_object($query1)) {
echo "*".$row1->id."*";
foreach($secondary_result as $row2) {
echo "%".$row2->id."%";
}
}
Note, this method will be creating extra memory usage of storing the objects in an array, but it would save on CPU processing as you're not re-creating the objects over and over again, as well as calling a function.
If you just print output, you can consider just saving the result first. No matter now many times you loop over $secondary_result, the final result will always be the same (as per your code, the first loop shows no signs of being directly influencing the second result).
In that case, this makes much more sense
$buffer = '';
while ($row2 = mysql_fetch_object($query2)) {
$buffer .= "%".$row2->id."%";
}
while($row1 = mysql_fetch_object($query1)) {
echo "*".$row1->id."*";
echo $buffer;
}
but I really don't know why you'd do that. If you're doing a nested loop, usually it's because the result of the first loop is affecting the second loop.
But I hope that helps!
Cheers!
EDIT
Per #Blazemonger's comment about looking ahead, the PDO equivalent would be: MySqli:Fetch-Object
When you have a result object from using the PDO function, you would loop like this:
while($row1 = $query1->fetch_object()) {
echo "*".$row1->id."*";
while ($row2 = $query1->fetch_object()) {
echo "%".$row2->id."%";
}
// put the result pointer back to the front
$query2->data_seek(0);
}
The above example shows both the fetch Object and pointer reset versions of MySqli.
The problem is that once you iterate fully through $query2, that's the end of your results. The next time through your $row1 loop, you're still at the end of $query2 and have no results left. Try using mysql_data_seek to go back to the start of your results:
while($row1 = mysql_fetch_object($query1)) {
echo "*".$row1->id."*";
mysql_data_seek($query2, 0);
while ($row2 = mysql_fetch_object($query2)) {
echo "%".$row2->id."%";
}
}
if you really need to repeat your second query data many times, get it into array first, and loop over this array as many times as you need.
First of all: The mysql_* functions are deprecated and will be removed in PHP 5.5. Consider using mysqli or PDO instead.
That being said; back to your question:
Each result set contains an internal pointer to one of the records in the result set. Initially, this pointer points to the first record, and is advanced with each call to mysql_fetch_object.
After your first inner loop, the internal pointer of the $query2 result set will already be at the end of the list, so subsequent calls to mysql_fetch_object will only return FALSE.
If your inner query depends on values from $row1, you will need to re-execute the second query within your outer loop. Otherwise, you can reset the result pointer with mysql_data_seek.
Perhaps you're not getting anything when you call $row2 = mysql_fetch_object($query2) which would give you the output you're getting.
After the first loop there are no more results for query2 to return. So the while is false in each additional loop. You would want to reset the query with mysqli_data_seek or storing all the data in a separate array and looping through that instead.
Please also note:
Per the documentation http://us2.php.net/manual/en/function.mysql-fetch-object.php
The mysql extension is deprecated as of PHP 5.5.0, and will be removed
in the future. Instead, the MySQLi or PDO_MySQL extension should be
used

Result is empty after while loop

Why is this not possible? Is there some way I can make the resolut not to be empty?
$sqlAllInfo = "SELECT item1, item2 FROM example";
$resAllInfo = mysql_query($sqlAllInfo);
while($rowAllInfo = mysql_fetch_assoc($resAllInfo)){
echo $rowAllInfo['item1'];
}
$rowAllInfo = mysql_fetch_assoc($resAllInfo);
echo $rowAllinfo['item2'];
Thanks for your time
No, the result will always be empty after your while loop, because the while loop extracts all value from the result resource..the while loop continues looping while there is still information to extract, and will finish when it is empty or when an error occurs
if you ment to get the last entry
$rowAllInfo still contains the last entry ;)
You are looping through the result set using while until there are no more results left. The while loop exits when mysql_fetch_assoc returns false, because there are no more results. Calling mysql_fetch_assoc again still means that there are no more results.
This line:
while($rowAllInfo = mysql_fetch_assoc($resAllInfo)){
assigns a new value to rowAllInfo and afterwards checks whether it is still "true"-ish (as "true" as PHP can be ;-) )
Now, after the last row is fetched, mysql_fetch_assoc() will return false, which is then assigned to $rowAllInfo. As $rowAllInfo is now "false", the loop will not execute anymore, but - look - it's too late! You Variable already has the value false assigned to it.
Even after that, you call mysql_fetch_assoc() once again. But, as you have already fetched all rows within your loop, no more rows are left, and once again $rowAllInfo is set to "false".
So, whatever you are trying to do - this is probably not your way. A common way to achieve what I understand you are trying to do is the following:
$allRows = array();
while( $row = mysql_fetch_assoc($res) ) {
$allRows[] = $row;
}
// show the array we just created...
echo print_r( $arrRows, 1 );

Categories