php:无法迭代每个循环

I am facing the follow error from the below code:

Error:

Warning: Invalid argument supplied for foreach() 

Code:

 //--------This is the code for jquery UI autocompleter-------------

include "inc/connect.php";
$skeyword = $_GET["term"];
$req = "SELECT  p.prm_title ,a.am_name, c.cm_name ,l.lm_name ,b.bm_name,r.pm_name  "
    . "FROM product_master p,author_master a,category_master c,language_master l,binding_master b ,publisher_master r "
    . "WHERE p.prm_title LIKE '%$skeyword%' OR a.am_name LIKE '%$skeyword%'
       OR c.cm_name LIKE '%$skeyword%' OR l.lm_name LIKE '%$skeyword%' OR b.bm_name LIKE '%$skeyword%' OR r.pm_name LIKE '%$skeyword%'  
       GROUP BY p.prm_id LIMIT 10";

$res = mysql_query($req);
$ret = array();
foreach (mysql_fetch_array($res) as $row) {
    foreach ($row as $val) //--Error: from this line, Why?
    {
        if (false !== stripos($val, $skeyword)) {
            $ret[] = $val;
            break;
        }
    }
}

$testme = json_encode($ret);
echo $testme;

The above code is written for jquery auto-completer to search in many column field, but it will return only the matched column.

Please help me to solve this issue..

why:

If a variable:

  • is not array
  • does not implements the interface Iterator

and it is used to iterator by foreach, this error will raise.


How to fix

mysql_fetch_array returns an array of strings that corresponds to the fetched row, or FALSE if there are no more rows, so use a while loop to fetch result:

while ($row = mysql_fetch_array($res))
{
    // if $row is false, the code will not hit here.
    foreach ($row as $val)
    {
        if (FALSE !== stripos($val, $skeyword))
        {
            $ret[] = $val;
            break;
        }
    }
} 


update:

    while ($row = mysql_fetch_array($res))
    {
        // if $row is false, the code will not hit here.
        foreach ($row as $val)
        {
            if (FALSE !== stripos($val, $skeyword) && !in_array($val, $ret))
            {
                $ret[] = $val;
                break;  // what this break for?
            }
        }
    } 

Please try this. Use while instead of foreach

//--------This is the code for jquery UI autocompleter-------------

include "inc/connect.php";
$skeyword = $_GET["term"]; 
$req = "SELECT  p.prm_title ,a.am_name, c.cm_name ,l.lm_name ,b.bm_name,r.pm_name  "
        . "FROM product_master p,author_master a,category_master c,language_master l,binding_master b ,publisher_master r "
        . "WHERE p.prm_title LIKE '%$skeyword%' OR a.am_name LIKE '%$skeyword%'
                      OR c.cm_name LIKE '%$skeyword%' OR l.lm_name LIKE '%$skeyword%' OR b.bm_name LIKE '%$skeyword%' OR r.pm_name LIKE '%$skeyword%'  
                      GROUP BY p.prm_id LIMIT 10";

    $res = mysql_query($req);
            $ret = array();
            while ($row = mysql_fetch_array($res))
            {
                foreach ($row as $val)   //--Error: from this line, Why?
                {
                    if (FALSE !== stripos($val, $skeyword))
                    {
                        $ret[] = $val;
                        break;
                    }
                }
            } 

$testme = json_encode($ret);
echo $testme;
while ($row = mysql_fetch_array($res)) {

Again, but now as an answer:

Change your first foreach into a while loop. See the mysql_fetch_array manual

Please always verify that the parameter for the "foreach" is an array. Your SQL request may return FALSE if there is no row matching your conditions, and foreach on FALSE does not work :)

So after your code

foreach (mysql_fetch_array($res) as $row)

You have to verify that $row is an array and not false before trying to iterate over it.

if (is_array($row))

Or you may be more explicit and use mysql_num_rows, which tells you if the query returns some rows or not :

if (mysql_num_rows($res) > 0) 
{
    $ret = array();
    foreach ( mysql_fetch_array($res) as $row)
    // ...
}

But the right solution, as exposed above by djot and Amol, is to use the

while ($row = mysql_fetch_array($res))

which ensure that if $row is FALSE, then you won't enter the block and you won't try to iterate on FALSE.