Sunday 8 December 2019

php - 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




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();
}
}

Answer



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();
}
}

No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...