Jump to content

Messing around with 'while' loops


TechnoDiver
 Share

Recommended Posts

Hi, Freaks, I hope all are well.

I'm trying to make a while loop and there's a common manner used that I've seen in many, many example of code ->

<?php

while($row = mysqli_fetch_array($data_query)) {

...
}

and this manner of doing it auto-stops when it's to the end of the mysqli array. Using this exact way is not compatible with the syntax that I can use as I use a database wrapper that is highly abstracted.

for example, this would be the typical layout of a DB query for a user post ->

<?php

$table = "un_posts";
$field = "deleted";
$value = "no";
$rule = "ORDER BY id DESC";
$query = $this->_db->get($table, array($field, "=", $value), $rule);
$this->_data = $query->all(); // $this->_data is an array of objects

and this would be my typical way of assigning the data ->

<?php

foreach ($this->data() as $obj) {
  $post_data = array(
      "id" => $obj->id,
      "content" => $obj->content,
      "added_by" => $obj->add_by,
      "date_added" => date("F d, Y H:i:s", strtotime($obj->date_added)),
      "user_to" => $obj->user_to,
);

for project specific reasons I'd like to change this from a foreach loop to a while loop. What I found out is that the auto-stop of the while loop using the $row = mysqli.....

does not work if I do something like this ->

<?php

while($obj = $this->data()) {
  $post_data = array(
      "id" => $obj->id,
      "content" => $obj->content,
      "added_by" => $obj->add_by,
      "date_added" => date("F d, 20y H:i:s", strtotime($obj->date_added)),
      "user_to" => $obj->user_to,
	);

and it creates an infinite loop. Keeping in mind that $this->data() (I have a class method data() that returns $this->_data if anyone noticed the difference) is an array of objects why am I not getting the same result as

<?php

while($row = mysqli_fetch_array($data_query)) {

...
}

I don't understand. They're both arrays being looped through. What's the difference where mine isn't breaking the loop at the end but the mysqli array breaks the loop at the end of it?

Link to comment
Share on other sites

10 minutes ago, TechnoDiver said:

They're both arrays being looped through

no. the code using mysqli_fetch_xxxx statement is fetching a row of data from the result of the query, as an associative, a numeric array, or both (default is both), assigning the fetched row of data to the $row variable, then the while() conditional/loop statement is testing the true/false result from that fetch/assignment. this stops because when there is no more data to fetch, a false value is returned by the fetch statement. the while loop code works because the condition being tested changes from true to false when the end of the data is reached. the while loop code you proposed is assigning the whole array in $this->data() to $obj, each pass through the loop, which is always a true value for a non-empty array, so, the loop becomes a forever-loop.

while (pun intended) you can make a while() loop loop over an array, the php function needed to do so has been removed in php8, i.e. there's no good reason to change from using a foreach() loop to loop over an array of data.

what problem are you having by using a foeach loop that you are trying to solve?

 

 

 

Link to comment
Share on other sites

Where in the code does it cause "$this->data" to change?  Looks you just keep loading up the same data over and over.  And - shouldn't you have a set of square brackets on $post_data when you assign a new array to it?  If you WERE doing a loop on some new data each time thru your current code is only going to save one set of data that being the last one.

Link to comment
Share on other sites

Ok, thanks all. I didn't realize that the false return was built into the mysqli function. I guess I thought that breaking at the end was automatic by the while loop functionality. Knowing that, it's an easy fix ->

<?php

$cnt = 0;
while($cnt < count($this->data())) {
    $post_data = array(
        "id" => $this->data()[$cnt]->id,
        "content" => $this->data()[$cnt]->content,
        "added_by" => $this->data()[$cnt]->add_by,
        "date_added" => date("F d, 20y H:i:s", strtotime($this->data()[$cnt]->date_added)),
        "user_to" => $this->data()[$cnt]->user_to,
    );

 

22 minutes ago, mac_gyver said:

what problem are you having by using a foeach loop that you are trying to solve?

Not a problem, but I had a few if statements within the loop that seemed would work best if I could use 'break' and 'continue' if certain conditions weren't met, which I couldn't with the foreach()

 

21 minutes ago, ginerjm said:

Where in the code does it cause "$this->data" to change?

$this->_data is a private attribute of the class. I have a separate public function data()  that returns $this->_data.

 

All's good now though, my misunderstanding was in the functionality of the mysqli function and the while loop function. You folks explained it perfectly, thanks to you all

Edited by TechnoDiver
Link to comment
Share on other sites

The use of a while in your last is not wise.  You should use the foreach on $this->data.   Or get the count value ahead of the loop and then use a for using $i=0;$i<$cnt;$i++ and then use $i as the index into your array of query results.  OR stick with the foreach that you already showed.

Edited by ginerjm
Link to comment
Share on other sites

37 minutes ago, TechnoDiver said:
$cnt = 0;
while($cnt < count($this->data())) {
    $post_data = array(
        "id" => $this->data()[$cnt]->id,
        "content" => $this->data()[$cnt]->content,
        "added_by" => $this->data()[$cnt]->add_by,
        "date_added" => date("F d, 20y H:i:s", strtotime($this->data()[$cnt]->date_added)),
        "user_to" => $this->data()[$cnt]->user_to,
    );

this is a lot of unnecessary typing, processing, and evaluating the count() inside the loop statement is the slowest way to do this, just to convert an array of objects to an array of arrays (presumably you are doing something with $post_data on each pass through the loop) and to format the date/time. just originally fetch the data as an array of arrays, not of objects, and either format the date/time in the query or as a one-time operation on the fetched data.

Link to comment
Share on other sites

1 hour ago, TechnoDiver said:

Not a problem, but I had a few if statements within the loop that seemed would work best if I could use 'break' and 'continue' if certain conditions weren't met, which I couldn't with the foreach()

Why are you unable to use break and continue within a foreach() loop? From the manual

Quote

break 

(PHP 4, PHP 5, PHP 7, PHP 8 )

break ends execution of the current for, foreach, while, do-while or switch structure.

Quote

continue 

(PHP 4, PHP 5, PHP 7, PHP 8 )

continue is used within looping structures to skip the rest of the current loop iteration and continue execution at the condition evaluation and then the beginning of the next iteration.

Note: While the description for continue doesn't explicitly state it works for foreach() loops, the examples show that it clearly does.

Edited by Psycho
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.