Erreur: Call to a member function prepare() on null [Résolu]

Messages postés
84
Date d'inscription
mardi 13 janvier 2009
Dernière intervention
29 janvier 2019
-
Bonjour à tous,

J'ai besoin de votre aide pour resoudre une erreur qui ne rend vraiment fou.

Mon API se connecter à une db SQL Server comme suit (fichier config/db.php):
<?php 
 class sql { 
  private $connexion_sql;
  function __construct() { 
   $this->connexion_bdd = new PDO('sqlsrv:Server=servername;Database=db_name', 'username', 'password');
   // Fixe les options d'erreur (ici nous utiliserons les exceptions)
   $this->connexion_bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
  }
   
  public function requete($requete) { 
   $prepare = $this->connexion_bdd->prepare($requete); $prepare->execute();
   return $prepare;
  }
 }
 
 
?>


J'ai ensuite créé une classe de ma table fruit(objects/fruits.php):
<?php
 class Fruit{
 
  // database connection and table name
  private $conn;
  private $table_name = "tFruits";
  
  // object properties
  public $id;
  public $name;
  
  // constructor with $db as database connection
  public function __construct($db){
   $this->conn = $db;
  }
  
  // read products
  function read(){
   
   // select all query
   $query = "SELECT * FROM " . $this->table_name . " ORDER BY name ASC";
   
   // prepare query statement
   $stmt = $this->conn->prepare($query);
   
   // execute query
   $stmt->execute();
   
   return $stmt;
  }
 }
?>


Pour lire les fruits j'ai fait ceci (fruit/read.php) :
<?php
 // include database and object files
 include_once '../config/db.php';
 include_once '../objects/fruits.php';
 
 $sql = new sql();
 $db = $sql->__construct();
 
 //$req = $sql->requete('SELECT * FROM tFruits'); 
 //while ($r = $req->fetch()) { 
 /// print_r($r); 
 //}
 
 
 
 //$statement = 'SELECT * FROM tFruits';
 //$sth = $sql->prepare($statement, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
 //$num = $sth->rowCount();
 //$sth->execute();
 
 $fruit = new Fruit($db);
 // query fruits
 $stmt = $fruit->read();
 $num = $stmt->rowCount();
 
 if($num>0){
  
  // fruits array
  $fruits_arr=array();
  $fruits_arr["records"]=array();
  
  while ($row = $stmt->fetchAll(PDO::FETCH_ASSOC)){ 
   
   extract($row);
   
   $fruit_item=array(
    "id" => $id,
    "name" => $name
   );
  
   array_push($fruits_arr["records"], $fruit_item);
  }
  
  // set response code - 200 OK
  http_response_code(200);
  
  // show fruits data in json format
  echo json_encode($fruits_arr);
 }
 
 else{
 
  // set response code - 404 Not found
  http_response_code(404);
  
  // tell the user no products found
  echo json_encode(
   array("message" => "No fruits found.")
  );
 }
?>


lorsque je lance le fichier read.php dans u interpretur de json, j'obtiens l'erreur suivante:
Fatal error: Uncaught Error: Call to a member function prepare() on null in C:\....\objects\fruits.php on line 24


Cette ligne 24 du fichier fruits.php correspondau code suivant:
$stmt = $this->conn->prepare($query);


Fraichement je n'y comprends rien...

Alors, SVP j'ai besoin d'un coup de pousse.

Merci d'avance

EDIT : Correction des balises de code (ajout du langage )
Afficher la suite 

Votre réponse

5 réponses

Messages postés
24534
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
15 février 2019
362
0
Merci
Bonjour,

Plusieurs erreurs dans ton code....

Dans le fichier de connexion..
Tu as la variable
private $connexion_sql;

mais toi tu essayes de stocker la connexion dans :
$this->connexion_bdd


Ensuite...
Dans read.php
$sql = new sql();
 $db = $sql->__construct();

1 - la méthode construct est appellée automatiquement lors du new. (c'est un constructeur)
Il ne faut pas l'appeller ensuite....

2 - Tu penses que ton construct te retourne la connexion.... sauf que tu n'as aucun RETURN dans le code de ton constructeur....
A la limite, tu pourrais récupérer la variable $connexion_sql .. mais tu l'as déclaré en PRIVATE...
Donc.. soit tu code un GETTER pour pouvoir récupérer le contenu de cette variable (c'est le plus propre)
Soit tu ajoutes un RETURN dans ton construct()

3 - A la place... as tu déjà entendu parlé d'héritage ? De "extends" ?
Regarde donc... c'est bien pratique...
class sql { 
  protected $connexion_bdd;
  function __construct() { 
   $this->connexion_bdd = new PDO('sqlsrv:Server=servername;Database=db_name', 'username', 'password');
   // Fixe les options d'erreur (ici nous utiliserons les exceptions)
   $this->connexion_bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
  }

class Fruit extends bdd{
// database connection and table name
   private $table_name = "tFruits";
  
  // object properties
  public $id;
  public $name;
  
  // constructor with $db as database connection
  public function __construct($db){
    parent::_construct();
  }
 
 // read products
  function read(){
   
   // select all query
   $query = "SELECT * FROM " . $this->table_name . " ORDER BY name ASC";
   
   // prepare query statement
   $stmt = $this->connexion_bdd->prepare($query);






Commenter la réponse de jordane45
Messages postés
84
Date d'inscription
mardi 13 janvier 2009
Dernière intervention
29 janvier 2019
0
Merci
Grand merci a to jordane45,

j'ai apporte des modifications selon vos critiques et observations

le fichier db.php donne:
<?php 
class Database {

protected $connexion_bdd;
function __construct() {
$this->connexion_bdd = new PDO('sqlsrv:Server=DATA-SERVER\CHATBOTSERVER;Database=chatbotdb', 'sa', 'Germain09');
// Fixe les options d'erreur (ici nous utiliserons les exceptions)
$this->connexion_bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}

public function requete($requete) {
$prepare = $this->connexion_bdd->prepare($requete);
$prepare->execute();
return $prepare;
}

}

?>


Le fichier objects/fruits.php on a:
<?php


class Fruit extends Database{
// Nom de la table
private $table_name = "tFruits";

// object properties
public $id;
public $name;

// constructor with $db as database connection
public function __construct(){
parent::_construct();
}

// Lire les fruits
function read(){

// select all query
$query = "SELECT * FROM " . $this->table_name . " ORDER BY name ASC";

// preparer query statement
$stmt = $this->connexion_bdd->prepare($query);

// Executer query
$stmt->execute();

return $stmt;
}
}
?>


enfin le fichier fruit/read.php donne:
<?php
// required headers
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");

// inclure database et fichier object
include_once '../config/db.php';
include_once '../objects/fruits.php';

//Instancier la database
$database = new Database();

//Initialisation de l'objet fruits
$fruit = new Fruit();

// query fruits
$stmt = $fruit->read();
$num = $stmt->rowCount();

if($num>0){

// fruits array
$fruits_arr=array();
$fruits_arr["records"]=array();

while ($row = $stmt->fetchAll(PDO::FETCH_ASSOC)){

extract($row);

$fruit_item=array(
"id" => $id,
"name" => $name
);

array_push($fruits_arr["records"], $fruit_item);
}

// set response code - 200 OK
http_response_code(200);

// show fruits data in json format
echo json_encode($fruits_arr);
}

else{

// set response code - 404 Not found
http_response_code(404);

// tell the user no products found
echo json_encode(
array("message" => "No fruits found.")
);
}
?>


donc lorsque j'execute le fichier read.php, on obtient l'erreur suivante:
Fatal error: Uncaught Error: Call to undefined method Database::_construct() in ...\objects\fruits.php on line 14


Cette ligne correspond au code suivant:
public function __construct(){
parent::_construct();
}


Encore une fois, merci de m'apporter ton assistance.
Je suis un débutant |o|
jordane45
Messages postés
24534
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
15 février 2019
362 -
Il manque un underscore en effet
parent::_construct();

A remplacer par :
parent::__construct();
jordane45
Messages postés
24534
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
15 février 2019
362 -
tu noteras que le code que je te montre est en couleur.... contrairement au tient...
cela vient du fait que tu utilises mal les balises de code...

Explications sur leur fonctionnement ici :
https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code
Merci de le faire à l'avenir.
Commenter la réponse de lemega
Messages postés
84
Date d'inscription
mardi 13 janvier 2009
Dernière intervention
29 janvier 2019
0
Merci
Super, vraiment super....

Mais je pense qu'il y a un petit truc qui de fonctionne pas bien
Normalement, on doit avoir les donnees contenues dans la table tFruits
au lieu de cela on obtient
{
"message": "No fruits found."
}

comme si la table est vide.
jordane45
Messages postés
24534
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
15 février 2019
362 -
Essaye ça :

<?php

 class Database { 
  
  protected $connexion_bdd;
    
  function __construct() { 
      try{
        $this->connexion_bdd = new PDO('sqlsrv:Server=DATA-SERVER\CHATBOTSERVER;Database=chatbotdb', 'sa', 'Germain09');
        //  Fixe les options d'erreur (ici nous utiliserons les exceptions)
        $this->connexion_bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
      } catch(PDOException $e) {
          die('Erreur : ' . $e->getMessage());
      }
  }
  
    
  private function requete($requete,$datas=NULL) { 
      try{
        $prepare = $this->connexion_bdd->prepare($requete); 
        $prepare->execute($datas);
        return $prepare;
      }catch(Exception $e){
        // en cas d'erreur :
         return array('ERROR'=>" Erreur ! ".$e->getMessage());
      }
  }
    
    /**
    * Retourne tous les enregistrements d'une requête SELECT
    */
    public function db_All($sql,$datas=NULL){
      $prep = $this->requete($sql,$datas);
      return  empty($prep['ERROR']) ? $prep->fetchAll() : $prep['ERROR'];
    }
    
    /**
    * Retourne le premier enregistrements d'une requête SELECT
    */
    public function db_One($sql,$datas=NULL){
      $prep = $this->requete($sql,$datas);
      return  empty($prep['ERROR']) ? $prep->fetch() : $prep['ERROR'];
    }
    
    /**
    * Permet d'exécuter n'importe quel type de requête
    * A utiliser pour autre chose que les selects...
    */
    public function db_exec($sql,$datas=NULL){
      return $this->requete($sql,$datas);
    }

 }
 
?>

 <?php
 class Fruit extends Database{
  // Nom de la table
  private $table_name = "tFruits";
    
  // object properties
  public $id;
  public $name;
    
  // constructor with $db as database connection
  public function __construct(){
   parent::__construct();
  }
   
  /**
    * Retourne la liste des fruits
    * return Array
    */
  function read(){
        // select all query
        $query = "SELECT id, name FROM " . $this->table_name . " ORDER BY name ASC";
        $result = $this->db_All($query);
        return $result;
  }
    
    /**
    * Retourne Un des fruits en fonction de son id
    * param : id -> id d'un fruit
    * return Array contenant les infos d'un fruit
    */
  function get_FruitById($id){
        // select all query
        $query = "SELECT id, name FROM " . $this->table_name . " 
                  WHERE id =:id 
                  ORDER BY name ASC";
        $datas = array(':id'=>$id);         
        $result = $this->db_One($query,$datas);
        return $result;
  }
 }
?>

<?php
 // required headers
 header("Access-Control-Allow-Origin: *");
 header("Content-Type: application/json; charset=UTF-8");
 
 // inclure database et fichier object
 include_once '../config/db.php';
 include_once '../objects/fruits.php';
  
  function sendResponse($response,$statusCode=404){
    http_response_code($statusCode);
    echo json_encode($response);
  }
 
 //Instancier la database
 $database = new Database();
 
 //Initialisation de l'objet fruits
 $fruit = new Fruit();
 
 // query fruits
 $arrFruits = $fruit->read();
 $num = !empty($arrFruits) ? count($arrFruits) : 0;
 
 if($num>0){
  $response = array("records"=>$arrFruits);
  // set response code - 200 OK
  $codeResult = 200;
 } else{
   // set response code - 404 Not found
  $codeResult = 404;
  // tell the user no products found
   $response = array("message" => "No fruits found.")
 }
  
  sendResponse($response,$codeResult);
  
?>
Commenter la réponse de lemega
Messages postés
84
Date d'inscription
mardi 13 janvier 2009
Dernière intervention
29 janvier 2019
0
Merci
Wahou, merci de me montrer cette autre facette du php. ça montre tout son charme.. lol

On a l'erreur suivante :
 Error: Cannot use object of type PDOStatement as array in ...\config\dbase.php on line 34


Cette ligne correspond a :
return  empty($prep['ERROR']) ? $prep->fetchAll() : $prep['ERROR'];
jordane45
Messages postés
24534
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
15 février 2019
362 -
Ouppsssss.. en effet.

Change le ficher comme ceci :
class Database { 
  
  protected $connexion_bdd;
    
  function __construct() { 
      try{
        $this->connexion_bdd = new PDO('sqlsrv:Server=DATA-SERVER\CHATBOTSERVER;Database=chatbotdb', 'sa', 'Germain09');
        //  Fixe les options d'erreur (ici nous utiliserons les exceptions)
        $this->connexion_bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
      } catch(PDOException $e) {
          die('Erreur : ' . $e->getMessage());
      }
  }
  
    
  private function requete($requete,$datas=NULL) { 
      try{
        $prepare = $this->connexion_bdd->prepare($requete); 
        $prepare->execute($datas);
        return $prepare;
      }catch(Exception $e){
        // en cas d'erreur :
         print_r (array('ERROR'=>" Erreur ! ".$e->getMessage(),'SQL'=>$requete, 'datas'=>$datas);
         exit();
      }
  }
    
    /**
    * Retourne tous les enregistrements d'une requête SELECT
    */
    public function db_All($sql,$datas=NULL){
      $prep = $this->requete($sql,$datas);
      return  $prep->fetchAll() ;
    }
    
    /**
    * Retourne le premier enregistrements d'une requête SELECT
    */
    public function db_One($sql,$datas=NULL){
      $prep = $this->requete($sql,$datas);
      return  $prep->fetch();
    }
    
    /**
    * Permet d'exécuter n'importe quel type de requête
    * A utiliser pour autre chose que les selects...
    */
    public function db_exec($sql,$datas=NULL){
      return $this->requete($sql,$datas);
    }

 }
 
?>
Commenter la réponse de lemega
Messages postés
84
Date d'inscription
mardi 13 janvier 2009
Dernière intervention
29 janvier 2019
0
Merci
Ok.... Thank you.... Very good

Tout fonctionne a merveille. Voici le resultat:


Encore une fois merci, grand merci pour ton assistance.
Commenter la réponse de lemega

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.