I am getting this php error and I can't seem to fix it.
Fatal error: Call to a member function prepare() on a non-object in C:\xampp\htdocs\mlrst\database.php on line 26
here is the line that is calling function prepare.
$this->statement->prepare($strQuery);
and here is it being declared.
protected $statement;
any ideas?
Edit: Here is my full code (don't mind the testing dummies)
<?php
$d = new database(); // test
class database {
protected $db_connect;
protected $statement;
function database() {
$db_connect = new MySQLi("localhost", "root" ,"", "test") or die("Could not connect to the server.");
$statement = $db_connect->stmt_init();
$this->preparedQuery("INSERT INTO feedback (name, feedback) VALUES ('?', '?')");
$this->close();
echo "Done!";
}
protected function cleanString($strLine) {
$strCleansedLine = preg_replace("/[^a-zA-Z0-9\s]/", "", $strLine);
return $strCleansedLine;
}
public function preparedQuery($strQuery, $parameters = NULL) {
try {
$this->statement->prepare($strQuery);
$statement->bind_param("ss", $name, $feedback);
for ($i = 0; $i < count($parameters); $i++) {
}
$name = $this->cleanString("this is my name");
$feedback = $this->cleanString("this is some feedback");
$query = $statement->execute();
} catch(Exception $e) {
echo $e->getMessage();
}
}
protected function close() {
try {
if ($this->statement != NULL)
$this->statement->close();
if ($this->db_connect != NULL)
$this->db_connect->close();
} catch (Exception $e) {
$e->getMessage();
}
}
}
?>
You assigned the local variable $statement. You need to set the instance's property using $this->statement.
In other words, change this:
$statement = $db_connect->stmt_init();
To this:
$this->statement = $db_connect->stmt_init();
And this:
$statement->bind_param("ss", $name, $feedback);
To this:
$this->statement->bind_param("ss", $name, $feedback);
...and this:
$query = $statement->execute();
To this:
$query = $this->statement->execute();
Related
I created a function to grab data from my database. I want this function to be reusable just by placing correct arguments for different tables. Here's what I've done :
public function selectdata($table, $arguments='*', $where = null){
if($this->isconnect){
//check whether users put column names in the select clause
if(is_array($arguments)){
$new_args = implode(',', $arguments);
$sql = 'SELECT '.$new_args.' FROM '.$table;
} else {
$sql = 'SELECT '.$arguments.' FROM '.$table;
}
//check whether users use the where clause
if($where != null && is_array($where)){
$where = implode(' ', $where);
$sql .= ' WHERE '.$where ;
}
$query = $this->db->query($sql);
$query -> SetFetchMode(PDO::FETCH_NUM);
while($row = $query->fetch()){
print_r($row);
}
} else {
echo 'failed, moron';
}
}
And this is the way to run the function :
$columnname = array('bookname');
$where = array('bookid','=','2');
echo $database-> selectdata('buku', $columnname, $where);
The code worked quite decently so far, but I'm wondering how I want to use $where but without $columnname in the function. How do I pass the arguments in the function?
And could you point to me the better way to create a function to grab data using PDO?
Just use a PDO class which can look like this:
<?php
class DB_Connect{
var $dbh;
function __construct(){
$host = "xxx";
$db = "xxx";
$user = "xxx";
$password = "xxx";
$this -> dbh = $this -> db_connect($host, $db, $user, $password);
}
public function getDBConnection(){
return $this -> dbh;
}
protected function db_connect($host, $db, $user, $password){
//var_dump($host, $db, $user, $password);exit();
try {
$dbh = new PDO("mysql:host=$host;dbname=$db", $user, $password);
}
catch(PDOException $err) {
echo "Error: ".$err->getMessage()."<br/>";
die();
}
return $dbh;
}
public function query($statement){
$keyword = substr(strtoupper($statement), 0, strpos($statement, " "));
$dbh = $this->getDBConnection();
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;
}
}
}
?>
Now you can include that class and create an object with $dbh = new DB_Connect; and call every statement you want just with the reference on $dbh->query($statement)
This is my prefered way to do this.
EDIT: If you want to use a statement on another Database, just use the __construct($db) method to pass your database name on object creation
I am in the process of learning PDO and am trying to implement it in my current project. When I used mysqli, I could get detailed info about any error using mysqli_error($connection). I googled at what the comparable for PDO would be and found this post, and decided to implement it in my code. However, I am unable to get any error messages even when I know there is an obvious error in the sql statement.
Relevant code:
class Database {
public $connection;
function __construct() {
$this->open_database_connection();
}
public function open_database_connection() {
try {
$this->connection = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PASSWORD);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->connection->setAttribute( PDO::ATTR_EMULATE_PREPARES, false);
} catch(PDOException $e) {
echo $e->getMessage();
die('Could not connect');
}
} // end of open_database_connection method
public function query($sql, $params = []) {
try {
$query = $this->connection->prepare($sql);
} catch (Exception $e) {
var_dump('mysql error: ' . $e->getMessage());
}
foreach($params as $key => $value) {
if ($key === ':limit') {
$query->bindValue($key, $value, PDO::PARAM_INT);
} else {
$query -> bindValue($key, $value);
}
}
try {
$query->execute();
} catch(Exception $e) {
echo 'Exception -> ';
var_dump($e->getMessage());
}
/*
DID NOT WORK:
if (!$query->execute()) {
print_r($query->errorinfo());
}*/
$result = $query->fetchAll(PDO::FETCH_ASSOC);
$this->confirm_query($result);
return $result;
} // end of query method
function confirm_query($query) {
if (!$query) {
die('mysql error: ');
}
}
When I run the code, I do get the "mysql error", but I do not get any details about it. What am I doing wrong?
Update: As requested, I am providing additional details below.
What I am trying to do is get the user's login detail to be verified. To that end, once the user inputs his credentials , this code runs:
if (isset($_POST['submit'])) {
$username = trim($_POST['username']);
$password = trim($_POST['password']);
//check the database for the user
$user_found = User::verify_user($username, $password);
Relevant code from the User class:
public static function verify_user($username, $password) {
global $db;
$username = $db->escape_string($username);
$password = $db->escape_string($password);
$values = [ ":username" => $username,
":password" => $password,
":limit" => 1
];
$result_array = self::find_this_query("SELECT * FROM users WHERE username=:username AND password=:password LIMIT :limit", true, $values);
return !empty($result_array)? array_shift($result_array) : false;
}
public static function find_this_query($sql, $prepared = false, $params = []) {
global $db;
$the_object_array = array();
$result = $db->query($sql, $params);
$arr_length = count($result);
for ($i = 0; $i < $arr_length; $i++) {
$the_object_array[] = self::instantiation($result[$i]);
}
return $the_object_array;
}
public static function instantiation($the_record) {
$the_object =new self; //we need new self because $the_record corresponds to one user!
foreach($the_record as $the_attribute => $value) {
if ($the_object->has_the_attribute($the_attribute)) {
$the_object->$the_attribute = $value;
}
}
return $the_object;
}
public function has_the_attribute($attribute) {
$object_properties = get_object_vars($this);
return array_key_exists($attribute, $object_properties);
}
You have to use PDO::errorInfo():
(...)
public function query($sql, $params = []) {
try {
$query = $this->connection->prepare($sql);
if( !$query )
{
$error = $this->connection->errorInfo();
die( "mysql error: {$error[2]}" );
}
} catch (Exception $e) {
var_dump('mysql error: ' . $e->getMessage());
}
(...)
}
PDO::errorInfo returns an array:
Element 0: SQLSTATE error code (a five characters alphanumeric identifier defined in the ANSI SQL standard);
Element 1: Driver-specific error code;
Element 2: Driver-specific error message.
I've tried disabling emulated prepares in PDO but I cannot get it to work. Everything else works. The query is successful. The reason I believe it's not working is because it does not escape quotes and such so I get syntax errors.
I've tried doing it two different ways.
$this->dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
and
$insert = $database->$con->prepare($insert, array(PDO::ATTR_EMULATE_PREPARES => false));
I've also noticed that getAttribute does not work.
By doing this...
$emul = $database->$con->getAttribute(PDO::ATTR_EMULATE_PREPARES);
var_dump($emul);
...I get this error
SQLSTATE[IM001]: Driver does not support this function: driver does not support that attribute
And here's my database class where the action happens. (I might have left some unneccessary/stupid code in there while I was testing.)
<?php
class Database
{
public $dbh;
public $dbh1;
public $dbh2;
private static $instance;
public $numResults;
private $result = array(); // Results that are returned from the query
public function __construct()
{
try
{
$this->dbh = new PDO(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8', DB_USER, DB_PASS);
$this->dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->dbh1 = new PDO(DB_TYPE1.':host='.DB_HOST1.';dbname='.DB_NAME1.';charset=utf8', DB_USER1, DB_PASS1);
$this->dbh1->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->dbh1->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->dbh2 = new PDO(DB_TYPE2.':host='.DB_HOST2.';dbname='.DB_NAME2.';charset=utf8', DB_USER2, DB_PASS2);
$this->dbh2->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->dbh2->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e)
{
die("Database Error: ". $e->getMessage() . "<br />");
}
}
public static function getInstance()
{
if (!isset(self::$instance))
{
$object = __CLASS__;
self::$instance = new $object;
}
return self::$instance;
}
private function tableExists($table, $con)
{
switch($con)
{
case 'dbh':
$db_name = DB_NAME;
break;
case 'dbh1':
$db_name = DB_NAME1;
break;
case 'dbh2':
$db_name = DB_NAME2;
break;
}
$database = Database::getInstance();
if(is_array($table))
{
for($i = 0; $i < count($table); $i++)
{
$tablesInDb = $database->$con->prepare('SHOW TABLES FROM '.$db_name.' LIKE "'.$table[$i].'"');
$tablesInDb->execute();
$rowCount = $tablesInDb->rowCount();
if($tablesInDb)
{
if($rowCount <> 1)
{
die('Error: Table does not exist'.$table[$i]);
}
}
}
}else
{
$tablesInDb = $database->$con->prepare('SHOW TABLES FROM '.$db_name.' LIKE "'.$table.'"');
$tablesInDb->execute();
$rowCount = $tablesInDb->rowCount();
if($tablesInDb)
{
if($rowCount <> 1)
{
die('Error: Table does not exist'.$table);
}
}
}
return true;
}
public function insert($con, $table, $values, $cols = null)
{
if($this->tableExists($table, $con))
{
$insert = 'INSERT INTO '.$table;
if($cols != null)
{
$cols = implode(',', $cols);
$insert.= '('.$cols.')';
}
for($i = 0; $i < count($values); $i++)
{
if(is_string($values[$i]))
$values[$i] = "'".$values[$i]."'";
}
$values = implode(',', $values);
$insert .= ' VALUES ('.$values.')';
$database = Database::getInstance();
$insert = $database->$con->prepare($insert, array(PDO::ATTR_EMULATE_PREPARES => false));
$insert->execute();
if($insert)
{
return true;
}else
{
return false;
}
}
}
public function getResult()
{
return $this->result;
}
}
?>
As manual states, getAttribute() don't support ATTR_EMULATE_PREPARES
There shouldn't be no escaping with native prepares at all.
To check if you are in emulation mode or not you can use LIMIT clause with lazy binding. It will raise an error if emulation is on.
Your main problem is whatever "syntax error" you mentioned and you have to solve it first.
As Álvaro G. Vicario noted in comments, you are not using prepared statements. It is apparently the root of the problem. PDO doesn't "escape" your data by itself. It can do it only if you are using placeholders to represent your data in the query. You can read more here
This question already has an answer here:
php error Call to a member function query() on a non-object [closed]
(1 answer)
Closed 9 years ago.
i have this class for connect to MySql database and create/insert user but when work with this i see error.
My Auth Class is:
class AuthDB {
private $db;
public function __construct() {
$db = new Dbaccess();
if (!$db->connect ( DB_SERVER, DB_USER, DB_PASS, DB_NAME ) ) {
if (mysql_error() == '')
$database_incorrect = 'Database name is incorrect or doesn\'t exist';
else
$database_incorrect = 'ERROR: ';
echo $database_incorrect . mysql_error ();
}
}
public function createUser($email, $password, $salt, $verification) {
$ver = 0;
$act = 1;
$adm = 0;
$MYSQLDB = "INSERT INTO tbUsers (email, password, user_salt, is_verified, is_active, is_admin, verification_code) "
. "VALUES ('1', '1', '1', '1', '1', '1', '1')"; //test value
$r2 = $db->query ($MYSQLDB) or error ('Critical Error', mysql_error () ); // <<<LINE 30 ERROR HERE
if ($r2 > 0) {
return true;
}
return false;
}
}
My Dbaccess class Is:
class Dbaccess
{
var $q_array = array();
var $db_id;
var $query;
var $counter = 0;
var $timecounter = 0;
var $query_res;
function connect ($host, $login, $password, $db)
{
$this->host = $host;
$this->login = $login;
$this->password = $password;
$this->db = $db;
$this->db_id = #mysql_connect($this->host, $this->login, $this->password);
if ($this->db_id)
{
$db_select = #mysql_select_db($this->db);
$this->query("SET NAMES 'UTF8'");
if (!$db_select)
{
#mysql_close($this->db_id);
$this->db_id = $db_select;
}
else
return $this->db_id;
}
else
return false;
}
function close()
{
if($this->db_id)
{
if($this->query)
{
#mysql_free_result($this->query);
}
$result = #mysql_close($this->db_id);
return $result;
}
else {
return false;
}}
function query ($query)
//
// $db->query("QUERY");
{
unset($this->query_res);
if($query != "")
{
$sql_start = explode(' ', microtime());
$this->query_res = #mysql_query($query, $this->db_id);
$sql_stop = explode(' ', microtime());
$sql_time = $sql_stop[0] - $sql_start[0];
$sql_time+= $sql_stop[1] - $sql_start[1];
$this->timecounter+= round($sql_time, 5);
$this->counter++;
}
if($this->query_res)
{
unset($this->q_array[$this->query_res]);
return $this->query_res;
}
else
{
return false;
}
}
}
Now i see this error when send data :
Fatal error: Call to a member function query() on a non-object in C:\xampp\htdocs\test\classes\Auth.php on line 30
How to Fix This Error? Where is my mistake?
You want this in your __construct:
public function __construct() {
$this->db = new Dbaccess();
And when you query, you want:
$this->db->query($MYSQLDB);
When you just use the variable $db, it only exists within the scope of that method. But when you use class properties it exists within the scope of the entire class.
This question already has answers here:
Call to a member function on a non-object [duplicate]
(8 answers)
Closed 10 years ago.
I'm new to php oop.here i wanted to do database connectivity with singleton class but i got error like this:
Fatal error: Call to a member function getOne() on a non-object in C:\xampp\htdocs\singleton\new\singleton_db.php
here i have given two file
1.singleton_db.php
<?php
class database
{
public $query;
public $results;
public $conn;
public static $database;
//connect to the database
public function __construct()
{
$this->conn = mysql_connect('localhost','root','');
if ($this->conn)
{
mysql_select_db('test1');
}
}
public static function instance()
{
if (!isset(self::$database)) {
self::$database = new database();
}
return self::$database;
}
function getOne($sql) {
$result = $this->conn->getOne($sql); //Error in this line
if(database::isError($result)) {
throw new Exception($result->getMessage(), $result->getCode());
}
return $result;
}
function startTransaction() {
//autoCommit returns true/false if the command succeeds
return $this->conn->autoCommit(false);
}
function commit() {
$result = $this->conn->commit();
if(database::isError($result)) {
throw new Exception($result->getMessage(), $result->getCode());
}
$this->conn->autoCommit(true);
return true;
}
function abort() {
$result = $this->conn->rollback();
if(database::isError($result)) {
throw new Exception($result->getMessage(), $result->getCode());
}
return true;
}
//returns numerically indexed 1D array of values from the first column
public function insert($table, $arFieldValues) {
$fields = array_keys($arFieldValues);
$values = array_values($arFieldValues);
// Create a useful array of values
// that will be imploded to be the
// VALUES clause of the insert statement.
// Run the mysql_real_escape_string function on those
// values that are something other than numeric.
$escVals = array();
foreach($values as $val) {
if(! is_numeric($val)) {
//make sure the values are properly escaped
$val = "'" . mysql_real_escape_string($val) . "'";
}
$escVals[] = $val;
}
//generate the SQL statement
$sql = " INSERT INTO $table (";
$sql .= join(', ', $fields);
$sql .= ') VALUES(';
$sql .= join(', ', $escVals);
$sql .= ')';
$hRes = mysql_query($sql);
if(! is_resource($hRes)) {
$err = mysql_error($this->conn) . "\n" . $sql;
throw new Exception($err);
}
return mysql_affected_rows($hRes);
}
}
2.data.php
<?php
require_once('singleton_db.php');
try {
$db = database::instance();
} catch (Exception $e) {
// No point continuing...
die("Unable to connect to the database.");
}
$sql = "SELECT count(1) FROM mytable";
$count = $db->getOne($sql);
print "There are $count records in mytable!<br>\n";
// start a transaction
$db->startTransaction();
// do an insert and an update
try {
$arValues = array();
$arValues['id'] = '#id#';
$arValues['myval'] = 'blah blah blah';
$newID = $db->insert('mytable', $arValues);
print "The new record has the ID $newID<br>\n";
// update the record we just created
$arUpdate = array();
$arUpdate['myval'] = 'foobar baz!';
$affected = $db->update('mytable', $arUpdate, "id = $newID");
print "Updated $affected records<br>\n";
// write the changes to the database
$db->commit();
} catch (Exception $e) {
// some sort of error happened - abort the transaction
// and print the error message
$db->abort();
print "An error occurred.<br>\n" . $e->getMessage();
}
?>
What could I do to fix this ?
Your problem is you haven't defined the
getOne();
method properly. The property
$this->conn
Is just the result of mysql_connect() function which is a "MySQL link identifier on success, or FALSE on failure". It is not an object, and such, you can not ask it for the getOne(); method.