Is there a way to enable the use of fetch_assoc() several times on the same page with prepared statements?
$data = $conn->prepare("SELECT * FROM some_table WHERE id=?");
$data->bind_param('i',$id);
$data->execute();
$result = $data->get_result();
I'd like to be able to use fetch_assoc() on the same page as many times as I want as many different ways I want. If I want to loop twice, I should be able to do that. If I want to loop and do a single fetch, I should also be able to do that. Right now it seems, once fetch_assoc() is being used once, it cannot be used again on the same page.
In a loop
while($row = $result->fetch_assoc()){
...
}
Single fetch
$user = $result->fetch_assoc();
$first_name = $user['first_name'];
While technically possible (Nick shows how) to rewind the mysqli_result object, many people find it cumbersome to work with mysqli_result at all. It's much easier to fetch all the records into a PHP array and work with a multidimensional array instead of the mysqli_result object.
$result = $data->get_result()->fetch_all(MYSQLI_ASSOC);
This way you can do whatever you want with this array. You can filter, you can loop many times, you can use all the standard array functions in PHP.
$resultsFiltered = array_filter($results, fn($e) => $e['someColumn']>200);
foreach($resultsFiltered as $row) {
// only records with someColumn > 200
}
You can use mysqli_result::data_seek to reset the result pointer after each usage so you can loop over the results multiple times. For example:
while($row = $result->fetch_assoc()){
...
}
$result->data_seek(0);
while($row = $result->fetch_assoc()){
...
}
Related
This is how I get one record with MySQLi:
$result = $db->query("...");
$image = $result->fetch_object();
Now I need to get the comments and pass it to the view. I'm using the following snippet right now, but it doesn't seem right:
$result = $db->query("...");
while ($row = $result->fetch_object())
$comments[] = $row;
I'm wondering if there's a way to remove the loop?
Is there something like:
$image = $result->fetch_object(((s)))
So then my code would look like:
$result = $db->query("...");
$comments = $result->fetch_objects();
The mysqli_result class provides a fetch_all method to collect the full result set. However, that method will only return associative or numeric arrays (or a hybrid), not objects.
It's not possible to get an array of objects using mysqli_fetch_all(). The available options are: indexed array, associative array, or both.
Consider using the PHP Data Objects (PDO) interface, which has many more fetch modes and is thus superior to MySQLi in that regard.
Without seeing your SQL, it's tough to say. There may be a better query you could use. Post your SQL and I'll take another look.
In terms of your SQL query, if your query returns multiple rows, then you have already fetched them with one db call.
I don't see a way to collect into an array all of the comments, but you can clean up your code with a custom function.
function get_all_rows_as_array(&$result)
{
foreach($result as mysql_fetch_assoc($result))
{
$array[] = $row;
}
return $array;
}
$result = $db->query("...");
$comments = get_all_rows_as_array($result);
I was messing around with how to do queries from MySQL and show them on PHP and I stumbled upon something:
This is the table I'm doing the query to:
$query = mysqli_query($conexion, "SELECT * FROM notas");
while($nota = mysqli_fetch_assoc($query)){
var_dump($nota);
echo $nota["Descripcion"];
}
Whenever I use a while() to display all the results of the query, it works. This table have 2 rows and both of them are showing.
Result of the var_dump($notas):
But whenever I use a foreach(), it just returns me the last result of the query.
$query = mysqli_query($conexion, "SELECT * FROM notas");
foreach(mysqli_fetch_assoc($query) as $valor){
var_dump($valor);
}
Result of the var_dump($valor):
Is there any reason why? I'm doing something wrong in the foreach() loop? I really can't tell. I would just say "fudge it", accept it and only use while loops to display queries, but, you know, want to know if I was doing something wrong or not understanding something.
The second version is looping through the columns, not the rows. It's equivalent to:
$row = mysqli_fetch_assoc($query);
foreach ($row as $valor) {
var_dump($valor);
}
You can see here that it's just fetching one row, which is an associative array, then looping through the elements of that array.
foreach (<expression> as <variable>) doesn't re-evaluate the expression every time through the loop. It executes it once, saves that array, then loops through the array elements.
The mysqli_result object is iterable, so you can do:
foreach($query as $valor) {
var_dump($valor);
}
You can also call mysqli_fetch_all($query), which will return a 2-dimensional array of all the results, and then loop through that. But if the query returns many results, this will use lots of memory.
Is there a way to enable the use of fetch_assoc() several times on the same page with prepared statements?
$data = $conn->prepare("SELECT * FROM some_table WHERE id=?");
$data->bind_param('i',$id);
$data->execute();
$result = $data->get_result();
I'd like to be able to use fetch_assoc() on the same page as many times as I want as many different ways I want. If I want to loop twice, I should be able to do that. If I want to loop and do a single fetch, I should also be able to do that. Right now it seems, once fetch_assoc() is being used once, it cannot be used again on the same page.
In a loop
while($row = $result->fetch_assoc()){
...
}
Single fetch
$user = $result->fetch_assoc();
$first_name = $user['first_name'];
While technically possible (Nick shows how) to rewind the mysqli_result object, many people find it cumbersome to work with mysqli_result at all. It's much easier to fetch all the records into a PHP array and work with a multidimensional array instead of the mysqli_result object.
$result = $data->get_result()->fetch_all(MYSQLI_ASSOC);
This way you can do whatever you want with this array. You can filter, you can loop many times, you can use all the standard array functions in PHP.
$resultsFiltered = array_filter($results, fn($e) => $e['someColumn']>200);
foreach($resultsFiltered as $row) {
// only records with someColumn > 200
}
You can use mysqli_result::data_seek to reset the result pointer after each usage so you can loop over the results multiple times. For example:
while($row = $result->fetch_assoc()){
...
}
$result->data_seek(0);
while($row = $result->fetch_assoc()){
...
}
I'm trying to create a while loop in PHP which retrieves data from a database and puts it into an array. This while loop should only work until the array its filling contains a certain value.
Is there a way to scan through the array and look for the value while the loop is still busy?
to put it bluntly;
$array = array();
$sql = mysql_query("SELECT * FROM table");
while($row = mysql_fetch_array($sql)){
//Do stuff
//add it to the array
while($array !=) //<-- I need to check the array here
}
You can use in_array function and break statement to check if value is in array and then stop looping.
First off, I think it'd be easier to check what you're filling the array with instead of checking the array itself. As the filled array grows, searching it will take longer and longer. Insted, consider:
$array = array_merge($array, $row);
if (in_array('ThisisWhatIneed', $row)
{
break;//leaves the while-loop
}
However, if you're query is returning more data, consider changing it to return what you need, only process the data that needs to be processed, otherwise, you might as well end up with code that does something like:
$stmt = $db->query('SELECT * FROM tbl');
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
if ($row['dataField'] === 'username')
{
$user = $row;
break;
}
}
WHERE could help a lot here, don't you think? As well taking advantage of MySQL's specific SELECT syntax, as in SELECT fields, you, need FROM table, which is more efficient.
You may also have noticed that the code above uses PDO, not mysql_*. Why? Simply because the mysql_* extension Is deprecated and should not be used anymore
Read what the red-warning-boxes tell you on every mysql* page. They're not just there to add some colour, and to liven things up. They are genuine wanrings.
Why don't you just check each value when it gets inserted into the array? It is much more efficient than iterating over the whole array each time you want to check.
$array = array();
$stopValue = ...
$sql = mysql_query("SELECT * FROM table");
while($row = mysql_fetch_assoc($sql)){
array_push($array,$row['column']);
if($row['column'] == $stopValue){
// The array now contains the stop value
break;
}
as the question states.
I have implemented a function wherein it fetches multiple rows from a database (*1) and then (*2) instantiate each row as an Object. After instantiation, the Objects are then stored into an array and then return the result to caller function and then iterates through the result array and displays each Object and add html formatting for each.
Here is the snippet of the code:
function find_all() {
//(*1) Fetch 30 comments from DB
$sql = 'SELECT * FROM comments';
$sql .= ' ORDER BY datetime DESC LIMIT 30';
return find_by_sql($sql);
}
function find_by_sql($sql='') {
global $database;
$result_set = $database->query($sql);
$object_array = array();
while($row = $database->fetch_array($result_set)) {
//(*2) Instantiate each row to a Comment object
// and then stores each comment to an object array
$object_array[] = Comment::instantiate($row);
}
return $object_array;
}
//(*3) Format and display each result.
$comments = find_all();
foreach ( $comments as $comment ) {
// Not sure if syntax is correct.. anyhow..
echo "<li>$comment->get_text()</li>";
}
However, I like the above approach since it's cleaner, easier to read, maintainable, and more OOP. But the problem is it takes a longer time to display than just simply iterating through each result than display each result once it's fetched, like so:
while ($row = mysql_fetch_array($sql)) {
echo "<li>$row['text']</li>";
}
I know the reason behind why it is slow. What I want to know is there a better way to solve the problem above?
While caching might be a good idea, it won't help because I need an updated list every time the list is fetched.
I think it can be a little faster if the script gets only the part you are interested in the result set, because fetch_array() returns 2 arrays with the same result set: associative, and numeric.
By adding MYSQLI_ASSOC (if you use mysqli): mysqli_fetch_array($result, MYSQLI_ASSOC), or try with mysql_fetch_assoc(), the script receives only the associative array.
You can test in pmpMyAdmin to see the diferences.