foreach can replace fetch_array?

6

I saw in a video that the guy takes the query and plays it right in the foreach and can list without any problem, my question is this: if it really is possible, using only the foreach would be much more practical than using while with fetch_array?

    
asked by anonymous 24.07.2016 / 22:03

2 answers

7

You can do everything at once with foreach , the question is really worth it.

To use foreach you would need to get the data, either with mysqli_fetch_all or accumulating somewhere with multiple readings, which is bad in some situations because you will anyway need to get all the data and store in memory if you want to use foreach .

For a request or an inaccessible website, this is irrelevant. In fact, with little data, mysqli_fetch_all may even be more "economical". For queries of large listings on a "contested" site, the thing already changes figure.

According to the PHP manual :

  mysqli_fetch_all () returns all the rows as an array in a single step, it may consume more memory than some similar functions such as mysqli_fetch_array (), which only returns one row at a time from the result set. Further, if you need to iterate over the result set, you will need a looping construct that will further impact performance. For these reasons mysqli_fetch_all () should only be used in those situations where the fetched result will be set to another layer for processing.

That, more or less, is as follows:

  

As mysqli_fetch_all () returns all rows as array in one step, it can consume more memory than similar functions as mysqli_fetch_array (), which only returns one line at a time in the result set. If you need to iterate over the results, you'll need a loop that impacts performance. For these reasons, mysqli_fetch_all () should only be used where the result needs to be sent for processing on another layer.

See example of using mysqli_fetch_all in reply from colleague @Inkeliz

In other words, using foreach does not dispense a series of fetch_array , fetch_assoc or function that does something similar, as mentioned.

A generally simpler way is to use while with mysqli_fetch_row or mysqli_fetch_assoc , since you will usually use the records one at a time and then release them later.

See a simple example of using while with mysqli_fetch_assoc :

<?php
    $link = mysqli_connect( ... );

    $result = mysqli_query($link, 'SELECT name, country FROM city ORDER BY name') or die ("Erro na query: %s\n", mysqli_error($link));

    while ($row = mysqli_fetch_assoc($result)) {
       printf ("%s (%s)\n", $row['name'], $row['country']);
    }

    mysqli_free_result($result);
    mysqli_close($link);
?>

There are similar examples on the PHP website itself:

  

link

    
24.07.2016 / 23:12
6

You can use mysqli_fetch_all() , thus making a foreach of the data already obtained.

In this way using:

$sql = mysqli_connect(...);

$Select = mysqli_query($sql, 'SELECT id, nome, idade FROM tabela WHERE 1 = 1');

$resultado = mysqli_fetch_all($Select, MYSQLI_NUM);

if(!!$resultado){
    foreach($resultado as list($id, $nome, $idade)){

      echo 'id>'.$id;
      echo 'nome>'.$nome;
      echo 'idade>'.$idade;
      echo '<br>';

    }
}

In this case I used list() so that each item of SELECT has a unique variable, this allows the code to be cleaner and not to use, for example: $item['id'] , $item['nome'] , $item['idade'] .

However you can do this quietly:

//...

$resultado = mysqli_fetch_all($Select, MYSQLI_ASSOC);

if(!!$resultado){
    foreach($resultado as $item){

      echo 'id>'.$item['id'];
      echo 'nome>'.$item['nome'];
      echo 'idade>'.$item['idade'];
      echo '<br>';

    }
}

In this case you will have to use MYSQLI_ASSOC instead of MYSQLI_NUM . The difference between them is that the first one will return an array whose indexes have the column name, while the second is only number. For example, the first one can get using $item['id'] , in the second it should use $item['0'] .

You can read more in the documentation at link .

Difference between mysqli_fetch_all() and mysqli_fetch_array() :

Regarding performance, it is extremely relative.

The PHP manual states that there may be more memory usage, as mentioned by @Bacco in your answer . But in the PHP documentation itself a user reported that this does not occur , never personally I noticed differences between the two, nowadays I use mysqli_fetch_all , but not for performance.

  

Note: mysqli_fetch_all() uses mysqlnd , you must use it. This is by default installed in PHP 5.4 and above, unless cheated.      If you do not have mysqlnd uninstall mysql ( yum remove php-mysql ) and install mysqlnd ( yum install php-mysqlnd ). : D

Looking at the mysqlnd source code we can find this in the 1806 line, see this by clicking here .

/* {{{ mysqlnd_res::fetch_all */
static void
MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES * result, const unsigned int flags, zval *return_value ZEND_FILE_LINE_DC)
{
    zval  row;
    zend_ulong i = 0;
    MYSQLND_RES_BUFFERED *set = result->stored_data;

    DBG_ENTER("mysqlnd_res::fetch_all");

    if ((!result->unbuf && !set)) {
        php_error_docref(NULL, E_WARNING, "fetch_all can be used only with buffered sets");
        if (result->conn) {
            SET_CLIENT_ERROR(result->conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "fetch_all can be used only with buffered sets");
        }
        RETVAL_NULL();
        DBG_VOID_RETURN;
    }

    /* 4 is a magic value. The cast is safe, if larger then the array will be later extended - no big deal :) */
    array_init_size(return_value, set? (unsigned int) set->row_count : 4);

    do {
        mysqlnd_fetch_into(result, flags, &row, MYSQLND_MYSQLI);
        if (Z_TYPE(row) != IS_ARRAY) {
            zval_ptr_dtor(&row);
            break;
        }
        add_index_zval(return_value, i++, &row);
    } while (1);

    DBG_VOID_RETURN;
}
/* }}} */

Apparently it executes a loop, so it delivers all the data. So using foreach you would be doing two loops ! A first one was made by the mysqlnd library when performing mysqli_fetch_all() and a second that is foreach , which its own code is executing. This could supposedly cause performance loss, in addition to obviously higher memory usage. : S

    
24.07.2016 / 23:35