I'm having trouble setting up PDO in my website framework.
I open my connection in "system.php" which is included at the beginning of every page with this code here
try {
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass,
array( PDO::ATTR_PERSISTENT => true));
}
catch(PDOException $e) {
echo $e->getMessage();
}
and on the same file (system.ph) I call this below it:
$STH = $DBH->query('SELECT value FROM settings WHERE type="theme"');
$STH->setFetchMode(PDO::FETCH_ASSOC);
while($row = $STH->fetch()) {
define('THEME', 'themes/'.$row['value'].'/');
}
Which works perfectly!
However, when I call the same query as above on "default.php" (which is included in the file) it comes back with:
Notice: Undefined variable: DBH in /pages/default.php on line 15
Fatal error: Call to a member function query() on a non-object
in /pages/default.php on line 15
What am I doing wrong here?
default.php
<?php
$STH = $DBH->query('SELECT value FROM settings WHERE type="theme"');
$STH->setFetchMode(PDO::FETCH_ASSOC);
while($row = $STH->fetch()) { echo $row['value']; }
?>
If it is inside a function add
global $DBH;
in the function before calling the query() function.
Seems like that file isn't getting included in default.php for whatever reason. Is there a boot strapper someplace that does the including for you before default.php is loaded?
Also, make sure that you're not getting an error on the path that loads default.php. It seems to me that $DBH would be undefined if there were an exception. Are you using output buffering someplace that might be cleared before you can see the echoing of the exception? You may want to consider logging your exceptions to a text file instead so that output buffering doesn't prevent you from seeing the errors which are occurring.
Related
I'm getting the error:
Call to a member function fetch() on a non-object
The line this refers to is:
$getProjectIdResult = $stmt->fetch();
Now, I think from this error that there must be something wrong with my database query, since the documentation says PDO query returns false on failure. I'm having trouble identifying what is causing the issue.
I've tried wrapping the fetch in a try/catch, with
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
However the catch isn't triggered and I just get the original fatal error so I haven't been able to get a more specific error.
classes.php
class Query extends Connection {
public function getProjectID($surveyID) {
$query_getProjectID = "SELECT projectID FROM test WHERE surveyID = :surveyID";
$query_getProjectID_params = array(
':surveyID' => $surveyID
);
try {
$stmt = $this->db->prepare($query_getProjectID);
$stmt = $stmt->execute($query_getProjectID_params);
}
catch (PDOException $ex) {
die("Failed to get project ID: " . $ex->getMessage());
}
$getProjectIdResult = $stmt->fetch();
$getProjectID = $getProjectIdResult['projectID'];
return $getProjectID;
}
}
test.php
include_once("includes/classes.php");
include_once("includes/functions.php");
// Bind $_GET data
// localhost/panel/test.php?surveyID=3&status=1&respondentID=666
// Expected result: 111
$surveyID = sanitise($_GET['surveyID']);
$status = sanitise($_GET['status']);
$respondentID = sanitise($_GET['respondentID']);
$con = new Connection();
$query = new Query();
$query->getProjectID($surveyID);
$con->closeConnection();
I've ruled out the sanitise function causing an issue by testing with and without it.
I apologise as I know this is probably just another amateur making another amateur mistake judging by how many posts there are by the same title.
When you call
$stmt = $stmt->execute($query_getProjectID_params);
You assign the return-value of execute() to $stmt, overwriting the variable, making it a boolean instead of an object. When you continue, $stmt no longer holds the PDOStatement object, but is now a boolean.
The solution is simply to remove the overwrite of your object, like this (remove $stmt = in front).
$stmt->execute($query_getProjectID_params);
http://php.net/pdostatement.execute
<?php
date_default_timezone_set('Europe/Istanbul');
try{
$db_host = 'localhost';
$db_name = 'db_name';
$db_kadi = 'root';
$db_sifre = '';
$pdo = new PDO("mysql:host=".$db_host."; dbname=".$db_name, $db_kadi, $db_sifre, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
}catch(PDOException $hata){
if($hata->getCode() == "1044"){
die("<h4>Sistem Bağlantı Hatası</h4><p>Sistem bağlantısı yok !</p>");
}else if($hata->getCode() == "1049"){
die("<h4>Database Sistem Hatası</h4><p>Database bağlantısı yok !</p>");
}
}
?>
<?php
public function fetch_data($data){
global $pdo;
$query = $pdo->prepare($data);
$query->closeCursor();
$query->execute();
return $query->fetch(PDO::FETCH_ASSOC);
$query->null;
}
?>
Fatal error: Call to a member function prepare() on null in
I do not understand how I got to this error. I've tried almost everything I encounter the same problem. If you have friends that will help me with this please write. Thank you
PDO module active, installed mysqli a stronge error.
The reason this is happening is because $data is null. When preparing the statement here ~>
$query = $pdo->prepare($data);
The data from your constructor is null. So go through and make sure wherever fetch_data is being called that the value you're passing isn't null.
EDIT:
It's because PDO is null. There must be something with how you're setting it up, as the global reference should give you access to the PDO.
Use this as a reference: http://www.w3schools.com/php/php_mysql_prepared_statements.asp
Well, first off, the error is that $pdo (even though you are using the global scope) is null. In your try, you are setting the $pdo variable, but if it fails, $pdo is never set. If $hata->getCode() doesn't return "1044" or "1049", the thread never dies.
Double check your connection string. Can you make a connection to it from your PC? I'm a little bit suspect of the '' password.
Fatal error: Call to a member function prepare() on null
Here's the explanation of that error:
$pdo->prepare($data);
You can call a method from $pdo only if $pdo is an object of a class with that method. In this case, $pdo is null, which is no type of object. A null has no methods, so it's a fatal error to try to call any method on a null.
The cause of this problem is that when you get a PDO connection, you're checking only error codes 1044 and 1049. If any other error code is the cause of the exception, then your code does not call die(), it proceeds to the second block of code.
But then $pdo still has not been set to a valid database connection!
It's like if you call someone on the phone, but your mobile phone has no signal. But you start talking to your friend anyway?!?
If the code in the catch() block is executing, it means something went wrong, and new PDO() was not successful. You must call die() in the catch() block one way or the other.
To fix this, I would recommend the following. In your catch() block, make sure you call die() by the end of the block, no matter what the error code is (example below).
I also recommend that you save the exception message into your error log. This is to help you troubleshoot. Don't display the error to users in the HTML output, because they don't know what that error means anyway. But you can look for it in your PHP error log (which is typically your Apache error log).
<?php
date_default_timezone_set('Europe/Istanbul');
try{
$db_host = 'localhost';
$db_name = 'db_name';
$db_kadi = 'root';
$db_sifre = '';
$pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_kadi, $db_sifre,
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
} catch (PDOException $hata) {
error_log($hata->getMessage()); // log the error!
if ($hata->getCode() == "1044") {
die("<h4>Sistem Bağlantı Hatası</h4><p>Sistem bağlantısı yok !</p>");
} else if ($hata->getCode() == "1049") {
die("<h4>Database Sistem Hatası</h4><p>Database bağlantısı yok !</p>");
}
// make sure to call die() if any other error code occurs!
die("<h4>Database Sistem Hatası</h4><p>Veritabanı yöneticisine başvurun !</p>"
}
?>
Once you do this, you can guarantee either $pdo is valid, or else the code has called die() and will not try to use an invalid $pdo.
I can't seem to use a array in a PDO statement here. It connects to the SQL Server properly, I just removed the user pass for security. When I run this script, it returns:
Call to undefined method PDOStatement::prepare()
I have no idea what I'm doing wrong. I've researched everywhere. Any help would be appreciated.
<?php
$hello = "foo";
try {
$bdd = new PDO("mysql:host=sql213.byethost16.com;dbname=b16_16742662_main", "b16_16742662", "00163827");
} catch(Exception $e){
die("ERROR : ".$e->getMessage());
}
$req = $bdd->prepare("SELECT * FROM ajax_chat_registered_members WHERE NAME=:UserName AND PASS=:UserPass");
$req->prepare(array('UserName'=>"Test",'UserPass'=>"foo"));
?>
I'm trying to read directly from the Magento database through a custom script that looks like this:
require_once 'app/Mage.php';
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$conn = Mage::getSingleton('core/resource')->getConnection('core_read');
echo var_dump($conn);
function getAitocAttr() {
$test = $conn->fetchAll("SELECT * FROM customer_entity");
var_dump($test);
}
getAitocAttr();
Nothing is showing up when I run this script. What am I doing wrong? The error I'm receiving is:
Fatal error: Call to a member function fetchAll() on a non-object
Thanks
Looking at your error message
Fatal error: Call to a member function fetchAll() on a non-object
PHP is complaining about a method call to fetchAll on a non-object. Looking at your code, the only place you call fetchAll is here.
function getAitocAttr() {
$test = $conn->fetchAll("SELECT * FROM customer_entity");
var_dump($test);
}
Within the getAitocAttr function there's no $conn variable defined. When you say
$conn = Mage::getSingleton('core/resource')->getConnection('core_read');
you've defined $conn outside the scope of the getAitocAttr function. You'll need to either define $conn inside getAitocAttr, or declare $conn as global inside getAitocAttr for this to work.
I'm not sure what the problem with your script is exactly. It looks OK however I have tackled the problem slightly differently to this and it works for me.
require_once 'app/Mage.php';
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$conn = Mage::getSingleton('core/resource')->getConnection('core_read');
echo var_dump($conn);
function getAitocAttr()
{
$sql = "SELECT * FROM customer_entity";
$result = $conn->query($sql);
echo "<pre>";
while ($row = $readresult->fetch()) {
print_r($row);
}
}
getAitocAttr();
I'm using the following script to use a database using PHP:
try{
$db = new PDO('mysql:host='.$host.';port='.$port.';dbname='.$db, $user, $pass, $options);
}
catch(Exception $e){
$GLOBALS['errors'][] = $e;
}
Now, I want to use this database handle to do a request using this code:
try{
$query = $db->prepare("INSERT INTO users (...) VALUES (...);");
$query->execute(array(
'...' => $...,
'...' => $...
));
}
catch(Exception $e){
$GLOBALS['errors'][] = $e;
}
Here is the problem:
When the connection to the DB is OK, everything works,
When the connection fails but I don't use the DB, I have the $GLOBALS['errors'][] array and the script is still running afterwards,
When the connection to the DB has failed, I get the following fatal error:
Notice: Undefined variable: db in C:\xampp\htdocs[...]\test.php on line 32
Fatal error: Call to a member function prepare() on a non-object in C:\xampp\htdocs[...]\test.php on line 32
Note: Line 32 is the $query = $db->prepare(...) instruction.
That is to say, the script crashes, and the try/catch seems to be useless. Do you know why this second try/catch don't works and how to solve it?
Thanks for the help!
EDIT: There are some really good replies. I've validated one which is not exactly what I wanted to do, but which is probably the best approach.
try/catch blocks only work for thrown exceptions (throw Exception or a subclass of Exception must be called). You cannot catch fatal errors using try/catch.
If your DB connection cannot be established, I would consider it fatal since you probably need your DB to do anything meaningful on the page.
PDO will throw an exception if the connection cannot be established. Your specific problem is that $db is not defined when you try to call a method with it so you get a null pointer (sort of) which is fatal. Rather than jump through if ($db == null) hoops as others are suggesting, you should just fix your code to make sure that $db is either always defined when you need it or have a less fragile way of making sure a DB connection is available in the code that uses it.
If you really want to "catch" fatal errors, use set_error_handler, but this still stops script execution on fatal errors.
In PHP7, we now can using try catch fatal error with simple work
try {
do some thing evil
} catch (Error $e) {
echo 'Now you can catch me!';
}
But usualy, we should avoid using catch Error, because it involve to miss code which is belong to programmer's reponsibility :-)
I will not report what has already been written about testing if $db is empty. Just add that a "clean" solution is to artificially create an exception if the connection to the database failed:
if ($db == NULL) throw new Exception('Connection failed.');
Insert the previous line in the try - catch as follow:
try{
// This line create an exception if $db is empty
if ($db == NULL) throw new Exception('Connection failed.');
$query = $db->prepare("INSERT INTO users (...) VALUES (...);");
$query->execute(array(
'...' => $...,
'...' => $...
));
}
catch(Exception $e){
$GLOBALS['errors'][] = $e;
}
Hope this will help others!
If database connection fails, $db from your first try .. catch block will be null. That's why later you cannot use a member of non-object, in your case $db->prepare(...). Before using this add
if ($db) {
// other try catch statement
}
This will ensure that you have db instance to work with it.
Try adding the following if statement :
if ($db) {
$query = $db->prepare("INSERT INTO users (...) VALUES (...);");
$query->execute(....);
}
else die('Connection lost');
try{
if(!is_null($db))
{
$query = $db->prepare("INSERT INTO users (...) VALUES (...);");
$query->execute(array(
'...' => $...,
'...' => $...
));
}
}
catch(Exception $e){
$GLOBALS['errors'][] = $e;
}