Error in foreach Invalid argument supplied for foreach ()

0

I'm going through an array of data with a foreach, but at the time of crossing it I release this Invalid argument supplied for foreach () and it tells me that the variables are undefined. This is my code:

<?php 

include 'Models.php';

class Restaurant extends Models{
    private $datos;

    public function __construct(){
        $this->datos=array();
        parent::__construct();
    }

    public function InfoRest(){

        session_start();
        $id = $_SESSION['usuario']['id_usuario'];
        $sql = $this->pdo->prepare("SELECT * FROM restaurants WHERE id_usuario = '$id'");
        $sql->execute();
        if($sql->rowCount()>=1){
            while($row=$sql->fetch()){
                $this->datos[]=$row;
            }
        return $this->datos;
        }else{
            $sql->errorInfo()[2];
        }
    }
}
?>

$obj = new Restaurant();
$values = $obj->InfoRest();
 foreach($values as $value){

 }

<?php echo $value['name_rest'] ?>

When I go through it, it throws me those errors. I have given a lot of laps but I can not even solve. I have done var_dump in the execute and it releases true, and in the same project I have something done in the same way and it does not throw error, for example this:

     class Models{

     protected $pdo;
     private $datos;

     public function __construct(){
        $this->datos=array();
        try{ 
            $this->pdo = new 
     PDO('mysql:host=localhost;dbname=vmenu.us;charset=utf8','root','');
            }
            catch(PDOExcepcion $e)
            { 
                echo $e->getMessage(); 
            exit; 
            }
      }

     public function DetailsRestaurant($id){

        $sql = $this->pdo->prepare("SELECT * FROM restaurants WHERE id_restaurant = :id");
        $sql->bindParam(':id',$id);
        $sql->execute();
        if($sql->rowCount()>=1){
            while($row = $sql->fetch()){
            $this->datos[]=$row;
            }
            return $this->datos;
        }else{
            $sql->errorInfo()[2];
        }

    }
 }

And then this in my Vista:

 $obj = new Models();
 $id = $_GET['id_restaurant'];
 $details = $obj->DetailsRestaurant($id);
  foreach($details as $result){
 }

 <?php echo $result['name_rest'] ?>

As you can see, it's the same

    
asked by Alejo Mendoza 12.02.2018 в 20:07
source

1 answer

1

There is an error in the approach to your function. If you want to verify that the user exists, you do not need to use numRows , but you can fill your array directly.

As in else you can return the error message, then you can verify if the array is empty in the destination.

The function could look like this (I've shielded it against SQL injection).

public function InfoRest(){

    session_start();
    $id = $_SESSION['usuario']['id_usuario'];
    $sql = $this->pdo->prepare("SELECT * FROM restaurants WHERE id_usuario = ?");
    $arrParams=array($id);
    $sql->execute($arrParams);

    if($sql){
        while($row=$sql->fetch()){
            $this->datos[]=$row;
        }
        return $this->datos;
    }else{
        return $sql->errorInfo()[2];
    }
}

And in the code to read it:

$obj = new Models();
 $id = $_GET['id_restaurant'];
 $details = $obj->DetailsRestaurant($id);
 print_r($details);

 foreach($details as $result){
      echo $result['name_rest'];
 }

NOTE: In InfoRest I would implement another more logical way to return the possible errors, which allows me to verify when receiving the data if there is any key with error.

In a future edition of the answer I could propose that solution if you are interested. I did not do it here so as not to get too far away from your code by going into other matters. The idea is to write a code that is consistent.

If you are not interested in this case the error message, you can do the following:

    if($sql){
        while($row=$sql->fetch()){
            $this->datos[]=$row;
        }
        return $this->datos;
    }else{
        return NULL;
    }

In this way, whether there is no data or if the query fails, you will return NULL and when you receive the data you only have to evaluate the variable:

 $obj = new Models();
 $id = $_GET['id_restaurant'];
 $details = $obj->DetailsRestaurant($id);

 if($details){
      foreach($details as $result){
          echo $result['name_rest'];
      }
 }else{
     echo "No se encontraron datos o la consulta falló";
 }

If you are interested in showing the user possible error messages of the query, then we will have three possible results:

  • That the query does not show data
  • There is an error in the query
  • Let the query show data
  • A consistent way to program here would be to return in all cases an array that could be NULL , have the error message with a key called error or an array with our data.

    Since here it seems to me that the query will not throw too many rows, I think we can use fetchAll to simplify. So we bring all the results in a variable $resultado . It can also be done as before, with while .

    The function would look like this:

    public function InfoRest(){
        session_start();
        $id = $_SESSION['usuario']['id_usuario'];
        $sql = $this->pdo->prepare("SELECT * FROM restaurants WHERE id_usuario = ?");
        $arrParams=array($id);
        $sql->execute($arrParams);
    
        if($sql){
            $resultado=$sql->fetchAll(PDO::FETCH_ASSOC);
            $this->datos[]=$resultado;
            return $this->datos;
        }else{
            return array ('error'=>$sql->errorInfo()[2]);
        }
    }
    

    And when you receive the data, you evaluate the three possible outcomes like this:

    $obj = new Models();
    $id = $_GET['id_restaurant'];
    $details = $obj->DetailsRestaurant($id);
    
    if(!$detail){
        echo "No se encontraron datos"; 
    }elseif (array_key_exists('error', $detail){
        echo $detail['error']; //Imprimirá el mensaje de error  
    }else{
          foreach($details as $result){
              echo $result['name_rest'];
          }
    }
    
        
    answered by 12.02.2018 / 20:37
    source