I'm writing a registration script that checks if the username already exists.
First I had troubles getting my database instance from databaseconnection.php to registration.php, this was the error: Call to undefined method DatabaseConnection::prepare().
But now I'm getting past the prepare() line and want to give my values to the query with bindValue(), but this next error is what I get 'Call to a member function bindValue() on a non-object'.
Does this still means I didn't get the correct database instance but a instance of the databaseconnection.php class?
This is databaseconnection.php
<?php
class DatabaseConnection {
private static $instance = null;
public $db_connection;
private function __construct(){
try{
$this->db_connection = new PDO('mysql:host='. DB_HOST .';dbname='. DB_NAME, DB_USER, DB_PASS);
$this->db_connection->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
return true;
} catch (PDOException $exception){
$this->errors[] = $this->lang['Database error'];
return false;
}
}
public static function getInstance(){
if(self::$instance === null){
self::$instance = new DatabaseConnection();
}
return self::$instance;
}
public function __call($method, $args) {
$callable = array($this->pdo, $method);
//is_callable, verify that the contents of a variable can be called as a function
if(is_callable($callable)) {
return call_user_func_array($callable, $args);
}
}
}
?>
In registration.php I use this code to get the instance into my local private variable:
class Registration
{
private $db_connection = null;
public function __construct()
{
$this->db_connection = databaseConnection::getInstance();
...
}
...
}
And would like to be able to execute this query in registration.php:
...
$check_username_query = $this->db_connection->prepare('SELECT user_name, user_email FROM users WHERE user_name=:user_name OR user_email=:user_email');
$check_username_query->bindValue(':user_name', $user_name, PDO::PARAM_STR);
$check_username_query->bindValue(':user_email', $user_email, PDO::PARAM_STR);
$check_username_query->execute();
$results = $check_username_query->fetchAll();
...
$callable = array($this->pdo, $method);
You have instance of PDO in $this->db_connection not $this->pdo
Related
Here is my config.php
<?php
define('DB_HOST', 'localhost');
define('DB_NAME', 'xxxx');
define('DB_USER', 'xxxx');
define('DB_PASS', 'xxxx');
?>
And It is DB.php
<?php
include 'config.php';
class DB {
public static $pdo;
public static function connection(){
if (!isset(self::$pdo)) {
try {
self::$pdo = new PDO('mysql:host='.DB_HOST.'; dbname ='.DB_NAME,DB_USER, DB_PASS);
}catch(PDOException $e){
echo $e->getMessage();
}
}
return self::$pdo;
}
public static function prepareOwn($sql){
return self::connection()->prepare($sql);
}
}
?>
3rd file is Student.php
<?php
include 'DB.php';
class Student {
public $table = 'student_info';
public function readAll(){
$sql = "SELECT * FROM $this->table";
$stmt = DB::prepareOwn($sql);
$stmt->execute();
return $stmt->fetchAll();
}
}
?>
But When I try to access readAll() from index.php using spl_autoload_register() Then I can see Fatal error: Call to undefined method DB::prepareOwn()
Can anyone help me to solve the problem??
Many thanks.
Sahidul
i copied your code into mine and saw your error. but as i guessed, first you will get an error with this line inside db.php:
return self::$pdo->prepare($sql);
Fatal error: Call to a member function prepare() on null
where prepare function came from? $pdo is just a static property in this class and it doesn't have a function called prepare! fix this line
Updated
the problem is you forgot to call connection method inside your prepareOwn. so your new prepareOwn function should be:
public static function prepareOwn($sql) {
self::connection();
return self::$pdo->prepare($sql);
}
i hope this code will work for you
class MySQLDatabase {
// Class attributes
private $host_name = "localhost";
private $database_name = "XXXXXXX";
private $database_username = "XXXXXXX";
private $database_password = "XXXXXXX";
private $is_connected;
private $connection;
private $statement ;
// construct
public function __construct() {
$this->open_connection();
}// End of construct
// connection method
public function open_connection() {
try {
$this->is_connected = TRUE ;
// PDO Connection
$this->connection = new PDO("mysql:host=".$this->host_name.";dbname=".$this->database_name.";charset=utf8",$this->database_username,$this->database_password);
// Error reporting
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->connection->setAttribute(PDO::ATTR_EMULATE_PREPARES,FALSE);
} catch(PDOException $errors) {
$this->is_connected = FALSE ;
self::catch_errors($errors);
}
}// End of open connection method
// Get connection method
public function connection(){
return $this->connection ;
}
// Close connection method
public function close_connection() {
$this->connection = null;
}// End of close connection method
private static function catch_errors($errors) {
echo("<h4><p>" . $errors -> getMessage() . "</p></h4>");
die();
}
// query method
public function query($sql){
return $this->statement = $this->connection->prepare($sql);
}
}// End of database class
$database = new MySQLDatabase();
class Student {
protected static $table = 'My_table';
public function readAll(){
global $database;
try{
$sql = "SELECT * FROM ". self::$table;
$stmt = $database->query($sql);
$stmt->execute();
return $stmt;
}catch(PDOException $error){
echo("<h4><p>" . $errors -> getMessage() . "</p></h4>");
die();
}
}
}
$c = new Student();
$s = $c->readAll();
$stmt = $s->fetchAll(PDO::FETCH_ASSOC);
foreach($s as $v){
var_dump($v);
}
This question already has an answer here:
Fatal error Call to a member function prepare() on null [closed]
(1 answer)
Closed 5 years ago.
I know there were a lot of answers related to this error, but I still don't know how to solve it... I'm trying to make the database connection, which would connect to the database and insert user's entered values in it and i got this error. I've created 2 files (with different classes):
Here is a connection file:
<?php
class Connection {
// Setting Database Source Name (DSN)
public function __construct() {
$dsn = 'mysql:host=localhost;dbname=employees';
// Setting options
$options = array (PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
// Making the connection to the database
try {
$this->dbh = new PDO($dsn, 'root', '', $options);
}
catch (PDOException $e) {
$this->error = $e->getMessage();
}
}
}
$connection = new connection();
?>
And here is users.php file:
<?php
include 'connection.php';
class Users {
public $name;
public $surname;
public $employmentDate;
public function __construct()
{
if(isset($_POST['Submit'])) {
$this->name = $_POST['name'];
$this->surname = $_POST['surname'];
$this->employmentDate = $_POST['employmentDate'];
}
}
// Inserting users values to the database table
public function insertUserValues() {
$stmt= 'INSERT INTO employee (name,surname,employment_date) VALUES (:name,:surname,:employmentDate)';
$stmt = $this->dbh->prepare();
$stmt->bindValue(':name',$name, PDO::PARAM_STR);
$stmt->bindValue(':surname',$surname, PDO::PARAM_STR);
$stmt->bindValue(':employmenDate',$employmentDate, PDO::PARAM_STR);
$stmt->execute([$this->name,$this->surname,$this->employmentDate]);
}
}
$users = new Users();
$users->insertUserValues();
?>
I guess there are some mistakes in code structure, but I'm just learning, so. The code line which throws the error 18 line in users.php file:
$stmt = $this->dbh->prepare();
Please someone tell me where I am doing a mistake, thank you for any help.
You just have somes mistakes in your code. Try to use this lines :
Connection file :
<?php
class Connection {
public $dbh;
// Setting Database Source Name (DSN)
public function __construct() {
$dsn = 'mysql:host=localhost;dbname=employees';
// Setting options
$options = array (PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
// Making the connection to the database
try {
$this->dbh = new PDO($dsn, 'root', '', $options);
}
catch (PDOException $e) {
$this->error = $e->getMessage();
}
}
}
$connection = new connection();
users.php file :
<?php
include 'connection.php';
class Users {
public $name;
public $surname;
public $employmentDate;
public $connection;
public function __construct($connection)
{
$this->connection = $connection;
if(isset($_POST['Submit'])) {
$this->name = $_POST['name'];
$this->surname = $_POST['surname'];
$this->employmentDate = $_POST['employmentDate'];
}
}
// Inserting users values to the database table
public function insertUserValues() {
$query = 'INSERT INTO employee (name,surname,employment_date) VALUES (:name,:surname,:employmentDate)';
$stmt = $this->connection->dbh->prepare($query);
$stmt->bindValue(':name',$this->name, PDO::PARAM_STR);
$stmt->bindValue(':surname',$this->surname, PDO::PARAM_STR);
$stmt->bindValue(':employmentDate',$this->employmentDate, PDO::PARAM_STR);
$stmt->execute();
}
}
$users = new Users($connection);
$users->insertUserValues();
Explanations :
You have to pass the $connection variable to your users class (or import it with global $connection;)
Your connection file has to make visible the dbh property, otherwise you will not be able to make any query on your database
PDO prepare() method is waiting for a query in first argument
You don't need to pass an array to execute() method if you already have binded your values before
You are referring to $this from outside the class scope. You probably want
$connection->dbh->prepare();
You could make your connection class to a singleton:
class Connection {
private static $instance = null;
// Setting Database Source Name (DSN)
public function __construct() {
$dsn = 'mysql:host=localhost;dbname=employees';
// Setting options
$options = array (PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
// Making the connection to the database
try {
$this->dbh = new PDO($dsn, 'root', '', $options);
} catch (PDOException $e) {
$this->error = $e->getMessage();
}
}
public static function __callStatic($name, $args) {
if (self::$instance == null) {
self::$instance = new self();
}
call_user_func_array([ self::$instance->dbh, $name], $args);
}
}
Then use it as follows:
Connection::prepare(); //or connection::any_pdo_function
I have a Database php file and a user php file. The Database is where I make my connection to the database.
<?php
/*
* Mysqli database class - only one connection
*/
class Database{
private $_connection;
private static $_instance; //The single instance
private $_host = 'localhost';
private $_username = 'root';
private $_password = '';
private $_database = 'blogwebsite';
public static function getInstance(){
if(!self::$_instance){ // If no instance make one
self::$_instance = new self();
}
return self::$_instance;
}
/*
* Constructor
*/
public function __construct(){
$this->_connection = new mysqli($this->_host, $this->_username,
$this->_password, $this->_database);
// Error handling
if(mysqli_connect_error()){
trigger_error("Failed to connect to MySQL: " .
mysqli_connect_errno(), E_USER_ERROR);
}else{
echo "You are connected to " . $this->_database;
}
}
// Magic method clone is empty to prevent duplication of connection
public function __clone(){ }
// Get mysqli connection
public function getConnection(){
return $this->_connection;
}
}
?>
This is the user page and I am including the Database page. I get an error that is saying ' Undefined variable: mysqli' AND 'Call to a member function prepare() on a non-object'.
<?php
include('class.database.php');
class api{
public function __construct(){
$db = Database::getInstance();
$mysqli = $db->getConnection();
}
public function getUsername($username){
$statement = $mysqli->prepare("SELECT username FROM users");
$statement->bind_param('s', $username);
$statement->execute();
$statement->bind_result($username);
$statement->fetch();
$statement->close();
return $username;
}
}
$username = new api();
echo $username->getUsername($username);
?>
Can anyone please help with any assistance. Thank you verry much.
You don't have a 'mysqli' variable in class 'api'. Also, you should call getConnection() after getting the Database instance.
class api{
private $mysqli;
public function __construct(){
$db = Database::getInstance()->getConnection();
$this->mysqli = $db->getConnection();
}
public function getUsername($username){
$statement = $this->mysqli->prepare("SELECT username FROM users");
$statement->bind_param('s', $username);
$statement->execute();
$statement->bind_result($username);
$statement->fetch();
$statement->close();
return $username;
}
}
You need to create a local variable $mysql :
class api{
protected $mysql; // <-- Here
public function __construct(){
$db = Database::getInstance();
$this->mysqli = $db->getConnection();
}
public function getUsername($username){
$statement = $this->mysqli->prepare("SELECT username FROM users");
$statement->bind_param('s', $username); // <-- what this for ?
$statement->execute();
$statement->bind_result($username);
$statement->fetch();
$statement->close();
return $username;
}
}
$username = new api();
echo $username->getUsername($username);
Hey guys I'm doing this wrong again I'm sure, but I'm trying to instantiate a PDO database
handler from my class Database from the file class.database.php inside my class AdminSession
from class.admin.php, somethings a bit screwy with my dependancy injection, and it is not
allowing me to use PDO's methods corretly; like fetch(), prepare() etcetra.
the class.database.php file
class Database
{
public $db; // handle of the db connection
private static $dsn="mysql:host=server2.com;dbname=database";
private static $user="user";
private static $pass="pass";
private static $instance;
public function __construct ()
{
$this->db = new PDO(self::$dsn,self::$user,self::$pass,$self::$opts);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->db->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
switch($_SERVER['ENVIRONMENT']) {
case 'staging':
self::$dsn="mysql:host=server1.com;dbname=database";
self::$user="user";
self::$pass="pass";
break;
default:
self::$dsn="mysql:host=server2.com;dbname=database";
self::$user="user";
self::$pass="pass";
}
}
public static function getInstance()
{
if(!isset(self::$instance))
{
$object= __CLASS__;
self::$instance=new $object;
}
return self::$instance;
}
}
and here's the topmost of my class.admin.php, and a method that is throwing an error.
right now the errors I'm getting
PHP Fatal error: Call to undefined method line 230
If I use $this->db-prepare($sql)
or
PHP Fatal error: Call to a member function prepare() on a non-object line 230
If I use $db-prepare($sql)
require('library/class.database.php');
class AdminSession {
static $abs_path;
public function __construct(Database $db) {
session_start();
self::$abs_path = dirname(dirname(__FILE__));
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$this->post = $_POST; // filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
if(get_magic_quotes_gpc ()) {
//get rid of magic quotes and slashes if present
array_walk_recursive($this->post, array($this, 'stripslash_gpc'));
}
}
$this->get = $_GET; // filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);
array_walk_recursive($this->get, array($this, 'urldecode'));
}
// other methods
private function checkDB($username, $password) {
$sql = "SELECT * FROM users WHERE username=:username";
try {
$db = Database::getInstance();
$stmt = $db->prepare($sql);
$stmt->bindParam("username", $username);
$stmt->execute();
$user = $stmt->fetchAll(PDO::FETCH_OBJ);
$db = null;
if($user) {
//general return
if(is_object($user[0]) && md5($user[0]->password) == $password) {
return true;
} else {
return false;
}
} else {
return false;
}
} catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
}
You can't put logic into your class definition. Instead, determine the value of these variables within the constructor. The switch will work in a method, but not when defining members.
Edit: I actually feel silly for missing this. The connection was made before the switch statement. I don't know that it'll fix the second set of issues ... but it'll behave properly for the original question now.
class Database
{
public $db; // handle of the db connection
private static $opts = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
private static $dsn="mysql:host=server2.com;dbname=database";
private static $user="user";
private static $pass="pass";
private static $instance;
public function __construct ()
{
switch($_SERVER['ENVIRONMENT']) {
case 'staging':
self::$dsn="mysql:host=server1.com;dbname=database";
self::$user="user";
self::$pass="pass";
break;
default:
self::$dsn="mysql:host=server2.com;dbname=database";
self::$user="user";
self::$pass="pass";
}
$this->db = new PDO(self::$dsn,self::$user,self::$pass,$self::$opts);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public static function getInstance()
{
if(!isset(self::$instance))
{
$object= __CLASS__;
self::$instance=new $object;
}
return self::$instance;
}
}
I have connection.php file where i am initializing PDO in the $db.
And i want to check this validation in the User.php which i include after connection.php.
but it is giving me error .
try {
$db = new PDO("mysql:dbname=$db_name;host=$db_host", $db_username,$db_password);
echo "PDO connection object created";
}
catch(PDOException $e){
echo $e->getMessage();
}
How can i validate this code by executing PDO.
How i will pass the PDO to the User Class..
Fatal error: Call to a member function query() on a non-object in /var/www/youngib/rahul/yapi/user.php on line 41
$sql="select * from users where email='$this->email'";
$rs=$db->query($sql);
if(mysql_num_rows($rs)>0){
$msg=geterrormsg(4);
//email already exist
echo $msg= "{ 'success': 'false','msg':'$msg' ,'error_code':'4' }";
return false;
}
Please Help.
Thanks .
Inject it in to the class or make a singleton DB class like...
Injection:
class User
{
protected $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
public function getDb()
{
return $this->db;
}
public function isUser($email)
{
$stmt = $this->getDb()->prepare('select count(email) as user_exists from users where email = :email');
return (bool) $stmt->execute(array(':email' => $email))->fetchColumn();
}
}
Singleton:
class Database {
protected $pdo;
protected static $instance;
protected function __construct($dsn, $user, $password)
{
$this->pdo = new PDO($dsn, $user, $password);
}
public static function getInstance()
{
if(!self::$instance)
{
// normally you would load the dsn, user, and password from a config file
$db = Config::get('db');
self::$instance = new self($db['dsn'], $db['user'], $db['password']);
}
return self::$instance;
}
public function getDb()
{
return $this->pdo;
}
}
class User
{
protected $db;
public function __construct(PDO $db = null)
{
if(null !== $db)
{
$this->db = $db;
}
}
public function getDb()
{
if(!$this->db)
{
$this->db = Database::getInstance()->getDb();
}
return $this->db;
}
public function isUser($email)
{
$stmt = $this->getDb()->prepare('select count(email) as user_exists from users where email = :email');
return (bool) $stmt->exectute(array(':email' => $email))->fetchColumn();
}
}
I hate to say this, but try just adding
global $db;
before your $db->query($sql); line. It might work, depending on exactly where the $db was created.
That said, prodigitalson's answer is a vastly improved approach, it just involves fixing your entire design, which involves more up front work :)