Erreur de portée-appel à une fonction membre prepare () sur un non-objet
donc le scénario est simple. J'utilise la classe qui fait quelque chose dans la base de données mais dans cette classe j'appelle une autre classe qui fait aussi quelque chose dans la base de données.
Merci, include_once a changé pour inclure et ça marche!
C'est ce que j'obtiens:
erreur Fatale: Appel à une fonction membre prepare() sur un non-objet -> mLog.php sur la ligne 20
j'utilise db_config.php pour créer un objet PDO et ensuite l'inclure dans mes classes.
db_config.php
try
{
$DBH = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
catch (PDOException $e)
{
echo $e->getMessage();
}
1ère classe mLog.php
<?php
class Log
{
public static function Add($action)
{
try
{
include_once "db_config.php";
$ip = $_SERVER['REMOTE_ADDR'];
$time = date('Y-m-d');
$values = array($ip, $action, $time);
//ERROR NEXT LINE
$STH = $DBH->prepare("INSERT INTO log (ip, action, time)
VALUES (?, ?, ?)");
$STH->execute($values);
$DBH = null;
$STH = null;
}
catch (PDOException $e)
{
echo $e->getMessage();
}
}
}
deuxième classe qui utilise la première classe (fragment car il est grand et a de nombreuses fonctions)
public static function Add($catName, $catDescr = "", $catImgURL = "", $catSubLevel = 0, $catSubID = 0)
{
try
{
include_once "db_config.php";
include_once "mLog.php";
$values = array($catName, $catDescr, $catImgURL, $catSubLevel, $catSubID);
$STH = $DBH->prepare("INSERT INTO cat (catName, catDescr, catImg, catSubLevel, catSubID)
VALUES (?, ?, ?, ?, ?)");
$STH->execute($values);
$DBH = null;
$STH = null;
//HERE IT IS
Log::Add("Added category 111" . $catName);
return true;
}
catch (PDOException $e)
{
echo $e->getMessage();
}
}
2 réponses
vous avez utilisé include_once "db_config.php";
au lieu de include "db_config.php";
.
comme je comprends de votre code, chaque fois que vous incluez db_config.php
, vous allez créer l'objet de base de données $DBH
.
puisque vous le mettez comme include_once
, il ne s'exécute que db_config.php une fois, et dans le journal de classe lorsque vous essayer de l'inclure, il ne fonctionnera pas puisqu'il a déjà été inclus dans la méthode Add.
améliorer cela, vous devez créer un classe qui gère uniquement (ou encapsule) l'objet AOP. Vous pouvez simplement créer une classe Singleton qui retourne l'objet PDO, inclure la classe une fois au sommet, et récupérer l'objet où que vous soyez dans le code.
exemple:
DBAccess.php
class DBAccess extends Singleton{
// there is a getInstance() method in the Singleton abstract class
private $dbh;
// The PDO object is created only once when the first getInstance() is called in Singleton.
function __construct(){
try
{
$this->dbh = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
$this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
catch (PDOException $e)
{
echo $e->getMessage();
}
}
/**
* Get the PDO object
* @return object
*/
public static function getDBH(){
return self::getInstance()->dbh;
}
}
Journal De Classe:
class Log
{
public static function Add($action)
{
try
{
$DBH = DBAccess::getDBH();
$ip = $_SERVER['REMOTE_ADDR'];
$time = date('Y-m-d');
$values = array($ip, $action, $time);
$STH = $DBH->prepare("INSERT INTO log (ip, action, time)
VALUES (?, ?, ?)");
$STH->execute($values);
}
catch (PDOException $e)
{
echo $e->getMessage();
}
}
}
Utilisation:
include_once ('db_config.php'); include_once ('mLog.php');
public static function Add($catName, $catDescr = '', $catImgURL = '', $catSubLevel = 0, $catSubID = 0)
{
try
{
$DBH = DBAccess::getDBH();
$values = array($catName, $catDescr, $catImgURL, $catSubLevel, $catSubID);
$STH = $DBH->prepare("INSERT INTO cat (catName, catDescr, catImg, catSubLevel, catSubID)
VALUES (?, ?, ?, ?, ?)");
$STH->execute($values);
$DBH = null;
Log::Add("Added category 111" . $catName);
return true;
}
catch (PDOException $e)
{
echo $e->getMessage();
}
}
le champ d'application de $DB
n'est pas dans les classes parce que vous ne l'avez pas passé dans les classes. En ce moment, il flotte simplement autour de la portée globale, mais pas dans le cadre de vos cours.
vous devez ajouter $DB
dans la classe Log
, vous pouvez le faire comme une variable statique comme si à l'intérieur de votre db_config.php
Log::$DB = $DB;
et utiliser comme ceci dans votre classe
class Log
{
public static $DB;
public static function Add($action)
{
try
{
include_once "db_config.php";
$ip = $_SERVER['REMOTE_ADDR'];
$time = date('Y-m-d');
$values = array($ip, $action, $time);
$STH = self::$DBH->prepare("INSERT INTO log (ip, action, time)
VALUES (?, ?, ?)");
$STH->execute($values);
self::$DBH = null;
$STH = null;
}
catch (PDOException $e)
{
echo $e->getMessage();
}
}
}