Scope error - Call to a member function prepare() on a non-object
So the scenario is simple. I use class that does something in database but in that class I call another class that also does something in DB.
Thanks, include_once changed to include and it works!
This is what I get:
Fatal error: Call to a member function prepare() on a non-object -> mLog.php on line 20
I use db_config.php to create PDO object and then include it in my 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();
}
1st class 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();
}
}
}
second class that uses first class (fragment because it's big and has many functions)
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();
}
}
You used include_once "db_config.php";
instead of include "db_config.php";
.
As I understand from your code, each time you include db_config.php
, you will create the database object $DBH
.
Since you put it as include_once
, it will only run db_config.php once, and in the log class when you try to include it, it will not run - since it has already been included in the Add method.
To improve on this, you should create a class that solely manages (or encapsulate) the PDO object. You can simply create a Singleton class that returns the PDO object, include the class once at the top, and fetch the object where ever you are in the code.
Example:
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;
}
}
Log Class:
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();
}
}
}
Usage:
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();
}
}
The scope of $DB
isn't within the classes because you haven't passed it into the classes. At the moment its just floating around in global scope, but not within the scope of your classes.
You need to add $DB
into the Log
class, you can do this as a static variable like so inside your db_config.php
Log::$DB = $DB;
And use like this in your class
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();
}
}
}
精彩评论