Uncaught Error: Call to a member function prepare() (PDO, php) - php

I'm trying to get data from a table using a public function in PHP, but I get this error:
Uncaught Error: Call to a member function prepare() (PDO, php)
I'm searching for 2, 3 hours... But no result is similar or I did not understand.
<?php
class Config {
public static $SQL;
private function __construct() {
$host_name = "localhost";
$base_user = "root";
$base_pass = "";
$base_name = "home_page";
try {
self::$SQL = new PDO("mysql:host=$host_name;dbname=$base_name", $base_user, $base_pass);
self::$SQL->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
} catch(PDOException $e) {
die("Something went wrong, database connection closed. Reason: ". $e->getMessage());
}
}
public static function GetData($table, $data, $id) {
$wc = Config::$SQL->prepare('SELECT `'.$data.'` FROM `'.$table.'` WHERE `ID` = ?');
$wc->execute(array($id));
$r_data = $wc->fetch();
return $r_data[$data];
}
}
?>
And I use this in my base file:
<h1><?php echo Config::GetData("page_details", "Moto", 1) ?></h1>
The error is from this line:
$wc = self::$SQL->prepare('SELECT `'.$data.'` FROM `'.$table.'` WHERE `ID` = ?');

Is there any particular reason why you want to use STATICeverywhere? The common approach is using public, dynamic methods and properties. I rewrote your sample with suggested naming convention in PHPs OOP, it works:
<?php
class Config
{
/** #var PDO $conn */
private $conn = null;
public function __construct()
{
$host_name = "localhost";
$base_user = "root";
$base_pass = "";
$base_name = "home_page";
try {
$this->conn = new PDO("mysql:host=$host_name;dbname=$base_name", $base_user, $base_pass);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully"; // <- this is unnnesesary
} catch (PDOException $e) {
die("Something went wrong, database connection closed. Reason: " . $e->getMessage());
}
}
public function findById($table, $data, $id)
{
$stmt = $this->conn->prepare('SELECT `' . $data . '` FROM `' . $table . '` WHERE `uid` = ?');
$stmt->execute(array($id));
return $stmt->fetch(PDO::FETCH_ASSOC);
}
}
// just for test
$cfg = new Config();
print_r($cfg->findById('foo', '*', 1));
or in your case
<?php echo $cfg->findById("page_details", "Moto", 1)['Moto'] ?>

Related

i have sql custom execution method, but there are found error unbuffered query

i have a class which has custom query execution. Then it shown some error if after i execute that.
SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
I have search out my problem answer but, almost of them recommend me to put $stmt->closeCursor() in my code, but i have done with it and still get error. The error shown is same with error above. Below is my DBClassification class. Please help me. Thanks :)
<?php
class DBClassification
{
public $db = null;
public $host = "localhost";
public $user = "root";
private $pass = "";
public $path = __DIR__ . "\\";
public $prefixFilename = "klasifikasi_";
public $dbexception = [];
public $stmt;
public function setHost($host){
$this->host = $host;
}
public function setUser($user){
$this->user = $user;
}
public function setPass($pass){
$this->pass = $pass;
}
public function setPath($path)
{
if (!is_dir($path)) die ("Directory \$path is not correct!\n$path");
$lastchar = substr($path, -1);
if ($lastchar != "/" && $lastchar != "\\") $path = $path . "/";
if (strpos($path, '/') !== false) $path = str_replace("/","\\",$path);
$this->path = $path . $this->host . "\\"; // setting path to the generated output file
}
public function setPrefixFilename($prefixFilename){
$this->prefixFilename = $prefixFilename;
}
public function setDBException($dbexception=[]){
$this->dbexception = $dbexception;
}
public function init($host,$user,$pass,$path,$prefixFilename,$dbexception=[])
{
if (!$dbexception) $dbexception = ["information_schema","mysql","performance_schema","phpmyadmin","sys"];
$this->setHost($host);
$this->setUser($user);
$this->setPass($pass);
$this->setPath($path);
$this->setPrefixFilename($prefixFilename);
$this->setDBException($dbexception);
$this->openConnection();
}
// Establishing Connection to mysql database on specified host
public function openConnection(){
try {
$db = new PDO("mysql:host=".$this->host, $this->user, $this->pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->db = $db;
return true;
} catch (PDOException $e) {
die("Error!: " . $e->getMessage());
}
return false;
}
public function run(){
try {
$databases = $this->stmtExec("SHOW DATABASES",true);
foreach($databases as $database): // execute each database
$dbname = $database['Database']; // database name
if(!in_array($dbname,$this->dbexception)): // prevent clasifying dbname which contain in dbexception
echo "USE $dbname\n";
$this->stmtExec("USE $dbname");
$tables = $this->stmtExec("SHOW TABLES",true);
endif; // if(!in_array($dbname,$dbexception)):
endforeach; // foreach($databases as $database):
} catch (Exception $e) {
echo "Something wrong, failed to clasify each database in host " . $this->host . "\n";
die("Error!: ".$e->getMessage());
}
}
public function stmtExec($sql,$fetch=false)
{
try {
$this->stmt = $this->db->prepare($sql);
if ($fetch) {
if ($this->stmt->execute()) $return = $this->stmt->fetchAll(PDO::FETCH_ASSOC);
} else {
$return = $this->stmt->execute();
}
$this->stmt->closeCursor();
} catch (PDOException $e) {
$errormsg = "db Error: ". $this->stmt->queryString . PHP_EOL . $e->getMessage();
$queryFilename = $this->path . "error.txt";
file_put_contents($queryFilename, $errormsg);
print_r($errormsg);die();
}
return $return;
}
}
[ANSWERED]
I have found the solution from that, i have to delete false status in pdo attribute "PDO::ATTR_EMULATE_PREPARES". I think it become error because it will check query in prepare method. And query "use $dbname" is one which has no output and will give error if prepare check is on. Thats all my opinion.

PDO throw error Undefined variable: pdo in

I have 3 files: dbconnect (here's declaration of $pdo), core.php (file with class to manage) and test.php.
I want to receive data from DB, but I have error:
Notice: Undefined variable: pdo in C:\xampp\htdocs\project\core.php on line 24
In dbconnect $pdo is in try catch, but before this I put: $pdo=null(to make variable accessible) but it doesn't work.
dbconnect ---> core.php(error here) ---> test.php;
//dbconnect.php
<?php
$mysql_host = 'localhost';
$username = 'root';
$password = '';
$database = 'db';
$pdo = null;
try {
$pdo = new PDO('mysql:host='.$mysql_host.';dbname='.$database.';charset=utf8', $username, $password );
}
catch(PDOException $e) {
echo 'Połączenie nie mogło zostać utworzone.<br />';
}
?>
//core.php
require_once('cms/dbconnect.php');
class getCore{
public $link_allegro;
public $link_facebook;
function getLinks(){
$query= $pdo->query('SELECT `url` FROM `links` WHERE `title` = "facebook"');
$row = $query->fetch();
$this->link_facebook = $row["url"];
$query= $pdo->query('SELECT url FROM links WHERE title = "allegro"');
$row = $query->fetch();
$this->link_allegro = $row["url"];
$query->closeCursor();
}
}
//test.php
<?php
require_once('core.php');
$tmp = new getCore;
$tmp->getLinks();
echo $tmp->link_allegro;
echo $tmp->link_facebook;
?>
Anyone can solve this? Thanks.
This is a scoping problem. $pdo doesn't exists in your getCore class.
You can make a DatabaseConnect class to manage your db access.
You can use this basic class for your database connection :
<?php
class DatabaseConnect {
private $mysql_host = 'localhost';
private $username = 'root';
private $password = '';
private $database = 'db';
private $pdo = null;
public function getPdo(){
return $this->pdo;
}
public function __construct(){
try {
$this->pdo = new PDO('mysql:host='.$mysql_host.';dbname='.$database.';charset=utf8', $username, $password );
}
catch(PDOException $e) {
echo 'Połączenie nie mogło zostać utworzone.<br />';
}
}
}
?>
You can getting your PDO instance in an other class with calling DatabaseConnect object -> getPdo() :
- Instannciate a new DatabaseConnect.
- Get PDO instance with the methof of the class.
Like that :
$databaseConnect = new DatabaseConnect();
$pdo = $databaseConnect->getPdo();
You next code :
//core.php
require_once('cms/dbconnect.php');
class getCore{
public $link_allegro;
public $link_facebook;
function getLinks(){
$databaseConnect = new DatabaseConnect();
$pdo = $databaseConnect-getPdo();
$query= $pdo->query('SELECT `url` FROM `links` WHERE `title` = "facebook"');
$row = $query->fetch();
$this->link_facebook = $row["url"];
$query= $pdo->query('SELECT url FROM links WHERE title = "allegro"');
$row = $query->fetch();
$this->link_allegro = $row["url"];
$query->closeCursor();
}
}
//test.php
<?php
require_once('core.php');
$tmp = new getCore;
$tmp->getLinks();
echo $tmp->link_allegro;
echo $tmp->link_facebook;
You need to pass $pdo to the getLinks() function as an input to make it available for use. you could try getLinks($pdo)

DB class wont load

I'm trying to connect using a simle db class. For some reason it only print out
"Initiate DB class"
test.php
include 'db.class.php';
echo 'Initiate DB class';
$db = new DB();
echo 'DB class did load';
db.class.php
class DB extends mysqli {
private static $instance = null;
private function __construct () {
parent::init();
$host = 'localhost';
$user = 'root';
$pass = 'MY_PASS';
$dbse = 'MY_DB';
parent::real_connect($host, $user, $pass, $dbse);
if (0 !== $this->connect_errno):
die('MySQL Error: '. mysqli_connect_error());
//throw new Exception('MySQL Error: '. mysqli_connect_error());
endif;
}
public function fetch ($sql, $id = null, $one = false) {
$retval = array();
if ($res = $this->query($sql)):
$index = 0;
while ($rs = $res->fetch_assoc()):
if ($one):
$retval = $rs; break;
else:
$retval[$id ? $rs[$id] : $index++] = $rs;
endif;
endwhile;
$res->close();
endif;
return $retval;
}
}
I have tried to search my log files for error but they come out empty.
Ok got it,
In your call to db your calling new DB(); which mean you're trying to call the constructor of your DB class.
In your DB class it looks like you're trying to create a singleton, but something is missing normally there would be something to assign the instance the database connection, and something that asks the instance if it's empty create a new connection or if it's not use the same instance.
At the end of the day to make this work you can change your constructor to public.
Try this:
Db_class:
class Db_class{
/***********************CONNECT TO DB*********************/
public function db_connect(){
$user = '***';
$db = '***';
$password = '***';
$host = '***';
try {
$dbh = new PDO("mysql:host=$host;dbname=$db", $user, $password);
}
catch(PDOException $err) {
echo "Error: ".$err->getMessage()."<br/>";
die();
}
return $dbh;
}
/******************PREPARE AND EXECUTE SQL STATEMENTS*****/
public function query($statement){
$keyword = substr(strtoupper($statement), 0, strpos($statement, " "));
$dbh = $this->db_connect();
if($dbh){
try{
$sql = $dbh->prepare($statement);
$exe = $sql->execute();
}
catch(PDOException $err){
return $err->getMessage();
}
switch($keyword){
case "SELECT":
$result = array();
while($row = $sql->fetch(PDO::FETCH_ASSOC)){
$result[] = $row;
}
return $result;
break;
default:
return $exe;
break;
}
}
else{
return false;
}
}
Other PHP:
$db = new Db_class();
$sql = "SQL STATEMENT";
$result = $db->query($sql);
Your constructor is marked as private which means new DB will raise an error. I see you have a private property to store an instance, are you missing the singleton method to return a new object?

DB pulling Function with PHP

I am very new to programming with PHP and am working on a fun little game to help myself learn. I got some code help from others on pulling a character's stats from the DB but am having trouble getting it to work. I just get "server error" when I try to run it right now. The Database information is fine, and I previously had a working function that pulled from the DB, but wanted to universalize it through a class function. Here is what I have so far.
DB class:
<?php
class db_class
{
//db connection portion
protected $mysqli;
private $db_host = 'XXXXXXX';
private $db_user = 'Filler';
private $db_password = 'Filler';
protected $db_name = 'Filler';
//db connection portion
public function __construct($db_host = null, $db_user = null, $db_password = null, $db_name = null) {
if (!empty($db_host)) {
$this->db_host = $db_host;
}
// validate other parameters similarly
//database connection object
$mysqli = new mysqli($this->db_host, $this->db_user, $this->db_password, $this->db_name);
if ($mysqli->connect_error) {
throw new Exception('Connect Error: ' . $mysqli->connect_errno . ', ' . $mysqli->connect_error);
} else {
$this->mysqli = $mysqli;
}
}
public function getPlayerStats($id) {
if (empty($id)) {
throw new Exception ('An empty value was passed for id');
}
// verify this is integer-like value
$id = (string) $id;
$pattern = '/^\d+$/';
if (!preg_match($pattern, $id) !== 1) {
throw new Exception ('A non-integer value was passed for id');
}
$id = (int) $id;
$query = "SELECT id, name, strength, defense, level, health, type, experience FROM characters WHERE id = :id";
$stmt = $this->mysqli->prepare($query);
$stmt->bind_param('i', $id);
$result = $stmt->execute();
if (false === $result) {
throw new Exception('Query error: ' . $stmt->error);
} else {
$obj = new stdClass();
$stmt->bind_result($obj->id, $obj->name, $obj->strength, $obj->defense, $obj->level, $obj, health, $obj->type, $obj->experience);
$stmt->fetch();
$stmt->close();
return $obj;
}
}
}
?>
DB class function call:
<?php
include "db_class.php";
echo "made it out here1";
$classobject = new db_class();
echo "made it out here2";
$results = $classobject->getPlayerStats('1');
print_r($results);
echo "made it out here3";
$id = "id: " . $results['id'];
$name = "name: " . $results['charname'];
$strength = "strength: " . $results['strength'];
$defense = "defense: " . $results['defense'];
$health = "health: " . $results['health'];
$level = "level: " . $results['level'];
$type = "type: " . $results['type'];
$experience = "experience: " . $results['experience'];
echo "<br/>";
echo "made it out here4";
?>
It is difficult to debug this code since I'm used to just putting in breaklines and running through coding errors in things like VBA in compilers, so any debugging tips would be greatly helpful. What am I doing wrong here? Thanks in advance!
You wrote
public __construct($db_host = NULL, ...
but constructors are functions. You need
public function __construct($db_host = NULL, ...
Your db_class constructor accepts four parameters. This instantiation passes none.
$classobject = new db_class();
So you end up with junk in your connection string. Sort that out and you'll be on your way.
You can avoid a lot of debugging by building minimal versions that work. For example, you can write this first.
<?php
class db_class{
public function __construct($db_host = NULL, $db_user = NULL, $db_password = NULL, $db_name = NULL) {
}
}
?>
If that works, check it in to version control, then add a little code to it. (How do you know whether it works? Test it.)

store multiple pdo connections in an array

so i have been trying to debug this issue myself for a few days now and i can't seem to figure out why i'm not getting the results I expect.
My code is rather complex and for a DB connection to be establish it spans across 3 Classes and one config file.
but basically my end usage ends up being
$this->db('test')->query('SELECT * FROM test1');
this establishes a connection to my database by the alias of test the query returns results so i'm good so far.
now my issue is when i try to make a new PDO object.
$this->db('test2')->query('SELECT * FROM test2');
this returns nothing because there is not table called test2 in my test1 object.
but if I do this
$this->db('test2')->query('SELECT * FROM test1');
now this returns the same results from the first PDO object.
I have traced and tracked down every line of code to make sure that the correct parameters are being passed to my database class and that each connection is properly established to the corresponding databases.
now my question is, can you have more than one datbase pdo connection? if so is there a special flag that needs to be set in the PDO options? are my connections being cached somewhere and causing this confusion?
this is my PDO declaration in each new class object stored in my array of connections
try
{
$this->_con = new PDO(
"mysql:host=" . $host . ";
port=" . $port . ";
dbname=" . $name, $user, $pass
);
$this->_con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
// TODO: push all $e methods to the developer debugger
echo "Database Error: ". $e->getMessage();
}
edit my code that uses the connection
step 1: a call to the parent class
public function __call($name, $params)
{
$class = $name . '_system_helper';
$hash = md5($class . $params);
if (class_exists($class))
{
if (!array_key_exists($hash, $this->_sys_helper))
{
if (method_exists($class, 'init'))
{
$this->_sys_helper[$hash] = call_user_func_array(array($class, 'init'), $params);
} else {
$this->_sys_helper[$hash] = call_user_func_array($class, $params);
}
}
return $this->_sys_helper[$hash];
}
return null;
}
step 2: called from the parent class
class DB_System_Helper extends Jinxup
{
private $_con = null;
public function __construct($end = null)
{
$mode = null;
$host = null;
$name = null;
$user = null;
$pass = null;
$port = null;
if (isset($this->config['database']['mode']))
{
$mode = $this->config['database']['mode'] == 'production' ? 'production' : 'development';
if (count($this->config['database'][$mode]) > 1)
{
foreach ($this->config['database'][$mode] as $key => $database)
{
if ($database['#attr']['alias'] == $end)
{
$host = $this->config['database'][$mode][$key]['host'];
$name = $this->config['database'][$mode][$key]['name'];
$user = $this->config['database'][$mode][$key]['user'];
$pass = $this->config['database'][$mode][$key]['pass'];
$port = $this->config['database'][$mode][$key]['port'];
}
}
} else {
$host = $this->config['database'][$mode]['host'];
$name = $this->config['database'][$mode]['name'];
$user = $this->config['database'][$mode]['user'];
$pass = $this->config['database'][$mode]['pass'];
$port = $this->config['database'][$mode]['port'];
}
$this->_con = new PDO_Database_Helper($host, $name, $user, $pass, $port);
} else {
echo 'No database mode specified';
}
}
public function __call($name, $param)
{
return call_user_func_array(array($this->_con, $name), $param);
}
}
step 3: called from DB_System_Helper
class PDO_Database_Helper extends Jinxup
{
private $_con = null;
private $_id = 0;
public function __construct($host, $name, $user, $pass, $port = 3306)
{
try
{
$this->_con = new PDO(
"mysql:host=" . $host . ";
port=" . $port . ";
dbname=" . $name, $user, $pass
);
$this->_con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
// TODO: push all $e methods to the developer debugger
echo "Database Error: ". $e->getMessage();
}
}
[...]
}
Are you sure that the hashing you're doing is enough to "namespace" each connection in the $this->_sys_helper array?
I suspect the problem lies in the first stage.
public function __call($name, $params)
{
$class = $name . '_system_helper';
$hash = md5($class . $params);
if (class_exists($class))
{
if (!array_key_exists($hash, $this->_sys_helper))
{
if (method_exists($class, 'init'))
{
$this->_sys_helper[$hash] = call_user_func_array(array($class, 'init'), $params);
} else {
$this->_sys_helper[$hash] = call_user_func_array($class, $params);
}
}
>>>>>>>>>>>>>> are you sure this is not returning the wrong
>>>>>>>>>>>>>> connection because of how the hashing is working?
return $this->_sys_helper[$hash];
}
return null;
}

Categories