I have a db.php file that has the following in it:
// db.php file
// creates connection to database
// DATABASE CONNECTION FUNCTION
function sql_con(){
try{
$dbh = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASS,
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
// log error to file and display friendly error to user
ExceptionErrorHandler($e);
exit;
}
}
I have a signup page and i want to check if username already exists, so i call my sql_con(); function beforehand to connect to database then do the below query
// connect to database
sql_con();
$stmt = $dbh->prepare("SELECT `user_login` FROM `users` WHERE `user_login` = ? LIMIT 1");
$stmt->execute(array($username));
if ( $stmt->rowCount() > 0 ) {
$error[] = 'Username already taken';
}
I'm very new to PDO and with the above i get the following errors:
Notice: Undefined variable: dbh in C:\wamp\www\signup.php on line 64
Fatal error: Call to a member function prepare() on a non-object in
C:\wamp\www\signup.php on line 64
Probably something very silly and I seem to confuse myself with PDO as I'm at the beginner stages. Could anyone tell me what I am doing wrong? Also I am not sure if this is the correct way as I'm new to PDO so if there's a more efficient way to do the username query check then please let me know.
This is because the $dbh object is limited to inside the try catch block and your sql_con() function due to scope.
The correct solution would be to remove the try catch block, and return the $dbh variable at the end of the sql_con() function.
Then:
try {
$dbh = sql_con();
$stmt = $dbh->prepare("SELECT `user_login` FROM `users` WHERE `user_login` = ? LIMIT 1");
$stmt->execute(array($username));
if ( $stmt->rowCount() > 0 ) {
$error[] = 'Username already taken';
}
}
catch (PDOException $e) {
//Do stuff with $e
}
The $dbh variable is destroyed once the function is done executing.
You could try returning the handle:
function sql_con() {
// your connection code
return $dbh;
}
Then in your signup page:
$dbh = sql_con();
Depending on your needs, a better alternative would be to employ a DI container.
You are defining pdo in function an ist not visible out it.
function sql_con(){
try{
$dbh = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASS,
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbh; //this
} catch (PDOException $e) {
// log error to file and display friendly error to user
ExceptionErrorHandler($e);
exit;
}
}
$dbh = sql_con();
It will be better if you create a class for pdo abstraction.
$dbh = DB::getInstance();
Related
I'm working on a simple login with mysql using pdo. Everything works fine so now I'm focusing on the error handling. But there's a problem. In my dbconfig I voluntarily saved the wrong psw/email/dbname to create an error.
<?php
session_start();
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'Captive');
define('DB_PASSWORD', 'arancione');
define('DB_DATABASE', 'geochimie');
function get_db() {
$dbhost=DB_SERVER;
$dbuser=DB_USERNAME;
$dbpass=DB_PASSWORD;
$dbname=DB_DATABASE;
try {
$dbConnection = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$dbConnection->exec("set names utf8");
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbConnection;
}
catch (PDOException $e) {
header("../pages/errore.php?errore=dbconfig");
}
}
?>
However, no error can be caught so when I prepare a statement using the db connection returned by get_db() I get this:
Uncaught Error: Call to a member function prepare() on null
Here is the php script where I prepare the stmt:
<?php
class Admin {
public function userLogin( $email,$password)
{
try{
$db = get_db();
$stmt = $db->prepare('SELECT id FROM admin WHERE email=:email AND psw=:hash_password');
$stmt->bindParam("email", $email,PDO::PARAM_STR) ;
$stmt->bindParam("hash_password", $password,PDO::PARAM_STR) ;
$stmt->execute();
$count=$stmt->rowCount();
$data=$stmt->fetch(PDO::FETCH_OBJ);
$db = null;
if($count)
{
$_SESSION['uid']=$data->id;
return true;
}
else
{
return false;
}
}
catch(PDOException $e) {
header("Location: ../pages/errore.php?errore=db");
}
}
}
?>
As you can see there is another try-catch but It doesn't work at the same way. Many thanks for your attention!
Ok guys, It seems that I needed to add die() or exit() after the header in the catch blocks. Now I can handle the errors properly.
This question already has answers here:
pdo - Call to a member function prepare() on a non-object [duplicate]
(8 answers)
Closed 6 years ago.
I'm writing a function to check for records in my database before executing anything, and i'm getting the error Call to a member function prepare() which i don't quite understand. I've been struggeling for quite some time now, and i'd really appriciate some help
The problem should be with the prepare() in line 19
<?php
$dsn = "xxx"; // Database Source Name
$username="xxx"; // User with acress to database. Root is MySQL admin.
$password="xxx"; //The user password.
try {
$conn = new PDO($dsn, $username, $password);
$conn ->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: ".$e->getMessage();
}
//------------------------ Does the category already exist? -------------------------
function checkuser($fbid,$fbfname,$fblname,$femail) {
$sql="SELECT COUNT(*) AS subjectcount FROM Users WHERE Fuid=:Fuid";
try {
$stmt = $conn->prepare($sql);
$stmt->bindValue(":Fuid",$_SESSION['FBID'], PDO::PARAM_INT);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$subjectcount=$row["subjectcount"];
} catch (PDOException $e) {
echo "Server Error - try again!".$e->getMessage();
}
//------------------------ If it dosn't, insert it -------------------------
if ($subjectcount==0) {
And i'm having a hard time debugging since i dont quite understand the cause of this error.
I updated my code to
<?php
$dsn = "xxx"; // Database Source Name
$username="xxx"; // User with acress to database. Root is MySQL admin.
$password="xxx"; //The user password.
try {
$conn = new PDO($dsn, $username, $password);
$conn ->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: ".$e->getMessage();
}
//------------------------ Does the category already exist? -------------------------
function checkuser($fbid,$fbfname,$fblname,$femail) {
global $conn;
$sql="SELECT COUNT(*) AS subjectcount FROM Users WHERE Fuid=:Fuid";
try {
$stmt = $conn->prepare($sql);
$stmt->bindValue(":Fuid",$_SESSION['FBID'], PDO::PARAM_INT);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$subjectcount=$row["subjectcount"];
} catch (PDOException $e) {
echo "Server Error - try again!".$e->getMessage();
exit;
}
//------------------------ If it dosn't, insert it -------------------------
if ($subjectcount==0) {
I guess the full error message is:
Fatal error: Call to a member function prepare() on a non-object
Right?
You are calling the member function (= function which is a member of a class instance) prepare of the variable $conn which is not declared in the scope of your checkuser function, it's declared outside (in global scope)!
To "import" it into your function so you can access it, put this line at the top of your function:
global $conn;
Also, it looks like you don't have full error reporting enabled, otherwise you would have seen this error before the fatal one, giving you another clue:
Notice: Undefined variable: conn
(By the way, you should exit; after outputing the DB error message in your catch block - otherwise you will print the error but continue to the rest, with a nonexisting DB connection!)
I am trying to use properties inside try catch blocks.
The try catch blocks are inside classes.
I want to extend a specific class, making it the subclass of the class which handles exceptions.
The problem is, that when I try to use those variables from the subclass, it always says undefined. I have to delete both of classes in order to catch the properties. After reading some other answers here by adding a return statement (I added return 1) outside, inside of the try catch block, it doesn't seem to work and it always says undefined variable.
Any help?
The language is php
The source code without classes works perfect:
try
{
//$pdo variable to insert PDO object information
$pdo = new PDO('mysql:host=localhost;dbname=studenti', 'root', '');
//Set php to catch exceptions
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//Set UTF-8 for character encodings
$pdo->exec('SET NAMES "utf8"');
}
//Catch error if unable to connect
catch(PDOException $e)
{
//error variable
$error = 'Unable to connect with database. ' . $e->getMessage();
//include file once and show on screen error message
include_once $_SERVER['DOCUMENT_ROOT'] . '/inc/error.inc.php';
//Exit and don't process further
exit();
}
//Another Exception handling
try
{
//Select statement
$sql = 'SELECT * FROM dega';
$select = $pdo->query($sql);
}
catch(PDOException $e)
{
//error variable
$error = 'Unable to select table. ' . $e->getMessage();
//include file once and show on screen error message
include_once $_SERVER['DOCUMENT_ROOT'] . '/inc/error.inc.php';
//Exit and don't process further
exit();
}
The source code with classes doesn't work:
<?php
//PDO class, connection with MySQL database
class Connect
{
function connection()
{
$pdo = null;
try
{
//$pdo variable to insert PDO object information
$pdo = new PDO('mysql:host=localhost;dbname=studenti', 'root', '');
//Set php to catch exceptions
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//Set UTF-8 for character encodings
$pdo->exec('SET NAMES "utf8"');
}
//Catch error if unable to connect
catch(PDOException $e)
{
//error variable
$error = 'Unable to connect with database. ' . $e->getMessage();
//include file once and show on screen error message
include_once $_SERVER['DOCUMENT_ROOT'] . '/inc/error.inc.php';
//Exit and don't process further
exit();
}
}
}
class Select extends Connect
{
function selection()
{
//Another Exception handling
try
{
//Select statement
$sql = 'SELECT * FROM dega';
$select = $pdo->query($sql);
}
catch(PDOException $e)
{
//error variable
$error = 'Unable to select table. ' . $e->getMessage();
//include file once and show on screen error message
include_once $_SERVER['DOCUMENT_ROOT'] . '/inc/error.inc.php';
//Exit and don't process further
exit();
}
}
}
//Output if successful
$error = 'Database connection established.';
include $_SERVER['DOCUMENT_ROOT'] . '/inc/error.inc.php';
?>
You have no subclass. Object Inheritance
You have no properties. Properties
Read about Classes and Objects.
class Connect
{
protected $pdo = null;
public function connection()
{
$pdo = null;
try
{
$this->pdo = new PDO('mysql:host=localhost;dbname=studenti', 'root', '');
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo->exec('SET NAMES "utf8"');
} catch (PDOException $e)
{
$error = 'Unable to connect with database. ' . $e->getMessage();
include_once $_SERVER['DOCUMENT_ROOT'] . '/inc/error.inc.php';
exit();
}
}
}
class Select extends Connect
{
function selection()
{
try
{
$sql = 'SELECT * FROM dega';
$select = $this->pdo->query($sql);
} catch (PDOException $e)
{
$error = 'Unable to select table. ' . $e->getMessage();
include_once $_SERVER['DOCUMENT_ROOT'] . '/inc/error.inc.php';
exit();
}
}
}
Put $pdo just before connection():
class Connect
{
protected $pdo = null; // or var $pdo = null;
function connection()
{
...
Inside the function it's a local variable not a class level property.
EDIT:
PHP requires $this-><class-variable> to access class properties inside functions. (Check out #Sectus's answer below.) Just using $pdo is creating a local variable on the fly (in both the methods) but gives an error in only selection() because that's where query() is being invoked without initializing a PDO() object first.
I'm working on my own SignUp class but it seems I have a problem with the PDO calls
The browser returns this to me:
Fatal error: Call to a member function query() on a non-object
I have my database configuration in a file included then on the main page. It's as follows:
<?
$dsn = 'mysql:dbname=magazin-online;host=localhost;';
$username = 'root';
$password = '';
try{
$pdo = new PDO($dsn, $username, $password);
}catch(PDOException $e){
echo 'Connection failed!: '.$e->getMessage();
}
An the line in the SignUp class causing the error is this:
$pdo->query("insert into ... () ... values ());
Now, I don't make any db connection in my SignUp class because I already included the file resposible for it.
How can I get rid of that error?
try using exec instead of query:
$pdo->exec("insert into ... () ... values ());
You are catching the exception generated by the new PDO, and then continue execution.
By doing it this way, you have to check that the class exists, so change:
if( $pdo)
$pdo->query("insert into ... () ... values ());
But .. a better way is not to continue execution after a critical error like this.
So better change the connection like this:
$dsn = 'mysql:dbname=magazin-online;host=localhost;';
$username = 'root';
$password = '';
try{
$pdo = new PDO($dsn, $username, $password);
}catch(PDOException $e){
echo 'Connection failed!: '.$e->getMessage();
die;
}
If I understand correctly, $pdo is a global variable. If you are calling $pdo->query inside a function, you either have to pass the $pdo connection as a parameter or declare it as global
global $pdo;
in the beginning of the member function.
I am trying to migrate a PHP app from MySQL to SQLite, and some things that used to work, simply stopped working now. I am using PDO through a custom database wrapper class (the class is a singleton, seems logical to do it like that).
The problem:
When trying to execute a query on a prepared statement, it throws a "fatal error: Call to a member function execute() on a non-object ...".
Relevant code (narrowed it down to this, after some hours of var_dumps and try-catch):
Connection string:
$this->connection = new PDO("sqlite:"._ROOT."/Storage/_sqlite/satori.sdb");
Obviously, the $connection variable here is a private variable from the class.
The error happens here (inside a function that is supposed to perform database insert):
try{
$statement = self::getInstance()->connection->prepare($sql);
}catch (PDOException $e){
print $e->getMessage;
}
try{
var_dump($statement);
$statement->execute($input);
}catch (Exception $e){
print $e->getMessage();
}
More accurately, it happens when I try to $statement->execute($input).
Any help appreciated. Thanks.
You are probably getting a mySQL error when the statement is being prepared, but you don't have PDO configured to throw an exception in case of an error.
<?php
$dbh = new PDO( /* your connection string */ );
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
// . . .
?>
try declaring the $statement variable outside the first try block. e.g.
$statement = null;
try{
$statement = self::getInstance()->connection->prepare($sql);
}catch (PDOException $e){
print $e->getMessage;
}
try{
var_dump($statement);
$statement->execute($input);
}catch (Exception $e){
print $e->getMessage();
}