I am working on a simple database helper for part of a test site. I want to be able to access a database by simply doing:
require_once 'include/database_system.php'
...
$row = DB_query("SELECT userID FROM users WHERE username = :username",
array(':username' => $ourUsername));
So I've written up a little script to do so:
<?php
session_start();
$username = "xxxx";
$password = "xxxx";
$host = "localhost";
$dbname = "xxxx";
$dboptions = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
try
{
$db = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
var_dump($db);
}
catch(PDOException $ex)
{
die("MySQL: Failed to connect to API Testing Database");
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
var_dump($db);
// break magic quotes
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
{
function break_magic_quotes(&$array)
{
foreach($array as &$value)
{
if(is_array($value))
{
break_magic_quotes($value);
}
else
{
$value = stripslashes($value);
}
}
}
break_magic_quotes($_POST);
break_magic_quotes($_GET);
break_magic_quotes($_COOKIE);
}
header('Content-Type: text/html; charset=utf-8');
function DB_query($query, $queryArgs)
{
global $db;
echo 'TRYING TO QUERY SERVER ';
var_dump($query);
var_dump($queryArgs);
var_dump($db);
try
{
echo 'PREPARE ';
$stmt = $db->prepare($query);
echo 'EXECUTE ';
$result = $stmt->execute($queryArgs);
}
catch(PDOException $ex)
{
echo "QUERY FAILED: $query";
die("Query failed: " . $query);
return;
}
echo 'SERVER QUERY OK';
return $stmt->fetch();
}
So naturally, I'm working on a bit of form action code for the login page, by doing:
require_once 'database.php'
....
$row = DB_query("SELECT * FROM users WHERE username = :username",
array(':username' => $_POST['u']) );
The output is not very conclusive at all. Not only does it fail to get past the $db->prepare() statement, but it doesn't even look like the PDO is valid.
object(PDO)#1 (0) { } object(PDO)#1 (0) { } TRYING TO LOGINobject(PDO)#1 (0) { } TRYING TO QUERY SERVER string(46) "SELECT * FROM users WHERE username = :username" array(1) { [":username"]=> string(4) "derp" } NULL PREPARE
I don't know why it would be doing any of this. I have checked the PHP settings and it looks like PDO is properly turned on. I have checked everything up and down and I haven't been able to get anywhere. If anyone has any insight, that would be great.
Related
I have a website that uses a MySql database for storing user info for signing in, and also my data. This site is hosted on a shared hosting server. The problem I'm running into is that I'm occasionally getting a SQL too many connections error. My max connections is set at the default 151.
I am using php for all my server side scripts, and using mysqli pdo connections.
Here is some sample code to show how I handle sql connections from my php scripts. I removed anything that wasn't relevant to the issue, such as input filtering, and character escaping.
<?php
require("common.php");
//get POST data
//My database query
$query = "
SELECT
id,
username,
password,
salt,
email
FROM users
WHERE
username = :username
";
//set params for prepared statements
$query_params = array(
':username' => $_POST['username']
);
try {
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
}
catch(PDOException $ex) {
$miscErr = "Something failed, please try again.";
}
$row = $stmt->fetch();
//do my password hashing, and checking, and sign in user using data in $row
}
?>
Here is my common.php where the error is thrown. I'm not sure what the correct way is to handle it, as i would like the code to try several times before failing.
<?php
$username = "username";
$password = "**************";
$host = "localhost";
$dbname = "mydbname";
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
$miscErr = "";
try {
$db = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password, $options);
}
catch(PDOException $ex) {
$miscErr = "Something failed, please try again";
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
I know this has been a while, but here is the solution that I came up with. Since there is no way for me to prevent the errors, i simply handle them with the following code in my common.php file.
$db = ""; // db object
$er = ""; // error object
/*setdb() is the function that actually gets and starts the db connection.
It returns either the db object, or false. The loop will try up to 5 times
to connect with .1 second breaks in between. if that fails then it logs an
error, and the page fails to load. This has not happened in over 5 months on
a live site.*/
for ($i = 0; $i = 5; $i++) { // short loop
if (setdb() !== false) {
$db = setdb(); // if successful breaks
break;
} else {
if ($i = 5) { // after 5 trys, logs error.
file_put_contents('sqlerror.er', $er . "\r\n", FILE_APPEND);
}
}
usleep(100000); // .1second sleep
}
function setdb(){
$username = "my-username";
$password = "***************";
$host = "localhost";
$dbname = "my_database";
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
$miscErr = "[1040] Too many connections";
try { // try to make connection
$db = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password, $options);
}
catch(PDOException $ex) {
$er = $ex;
$pos = strpos($ex, $miscErr);
if ($pos !== false) {
return false; //return false on error
}
file_put_contents('sqlerror.er', $ex . "\r\n", FILE_APPEND);
}
return $db; // return true
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
session_start();
I realize this question has been asked in some form or another multiple times, but none of the solutions on the other versions of this question work for me.
These two files have no issues:
/blog/login.php
<?php
include('core/init.php');
if (empty($_POST) === false){
$username = $_POST['username'];
$password = $_POST['password'];
if (empty($username) || empty($password)) {
$errors[] = 'Missing username and/or password.';
} else if (user_exists($username) === false) {
$errors[] = 'User doesn\'t exist.';
}else if (user_active($username) === false) {
$errors[] = 'User account not activated.';
}else {
//
}
print_r($errors);
}
?>
/blog/core/init.php
<?php
require('database/connect.php');
require('functions/users.php');
require('functions/general.php');
session_start();
$errors = array();
?>
I'm just including them to show you how connect.php is require()'d (indirectly) in users.php.
/blog/core/database/connect.php
<?php
$dbname = "xxx_forms";
$servername = "mysql.xxx.com";
$usr= "xxx_xxx";
$pass = "xxxxxxxx";
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $usr, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
?>
This connection itself doesn't trigger any errors...
/blog/core/functions/users.php
<?php
function user_exists($username) {
$ret = '';
try {
$sql = "SELECT COUNT(id) FROM registration WHERE user = '$username';";
$q = $pdo->query($sql);
$f = $q->fetch();
$ret = $f[0];
} catch (PDOException $e) {
die("Could not connect to the database $dbname :" . $e->getMessage());
}
return ($ret == 1) ? true : false;
}
However, when we get to users.php, I always get an error at the $q = $pdo->query($sql); line, apparently because PHP doesn't know what $pdo is. On the other hand, when I include the code from connect.php, so that it is not in an external file (exactly like below, but not commented out):
function user_exists($username) {
//$dbname = "xxx_forms";
//$servername = "mysql.xxx.com";
//$usr= "xxx_xxx";
//$pass = "xxxxxxxx";
$ret = '';
try {
//$pdo = new PDO("mysql:host=$host;dbname=$dbname", $usr, $pass);
$sql = "SELECT COUNT(id) FROM registration WHERE user = '$username';";
$q = $pdo->query($sql);
$f = $q->fetch();
$ret = $f[0];
} catch (PDOException $e) {
die("Could not connect to the database $dbname :" . $e->getMessage());
}
return ($ret == 1) ? true : false;
}
...everything works the way it is supposed to.
How do I make it work when the PDO connection is done in the external file connect.php?
Further to my comment, you need to do something like this:
/config.php
<?php
define('DS',DIRECTORY_SEPARATOR);
define('DB_HOST','localhost');
define('DB_NAME','database');
define('DB_USER','root');
define('DB_PASS','');
define('ROOT_DIR',__DIR__);
define('FUNCTIONS',ROOT_DIR.DS.'functions');
# Add the connection function
require_once(FUNCTIONS.DS.'connect.php');
# Start session
session_start();
# Get the connection
$pdo = connect();
/functions/connect.php
function connect()
{
$pdo = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASS);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
}
/functions/user_exists.php
<?php
function user_exists($pdo,$username)
{
$ret = 0;
try {
$sql = "SELECT COUNT(id) as count FROM registration WHERE user = :username";
$q = $pdo->prepare($sql);
$q->execute(array(":username"=>$username));
$f = $q->fetch(PDO::FETCH_ASSOC);
$ret = $f['count'];
}
catch (PDOException $e) {
die("Could not connect to the database ".DB_NAME.":" . $e->getMessage());
}
return ($ret == 1);
}
Here is an example of use:
/index.php
<?php
# Add the basic stuff
require(__DIR__.DIRECTORY_SEPARATOR.'config.php');
# Add our functions
require(FUNCTIONS.DS.'user_exists.php');
require(FUNCTIONS.DS.'general.php');
# Example of use
print_r(user_exists($pdo,'username#email.com'));
I can't figure this out. I've googled it and a lot of answers refer to blindValue as the solution but I've also tried that with no luck.
The problem is that the SELECT statement is returning zero records but it should return one record. If I hard code the values into the SQL statement it works but passing them in as parameters isn't. Can some one please help me out with this? Thanks.
<?php
function checklogin($email, $password){
try
{
// Connection
$conn;
include_once('connect.php');
// Build Query
$sql = 'SELECT pkUserID, Email, Password, fkUserGroupID FROM tbluser WHERE Email = :email AND Password = :password';
// $sql = 'SELECT pkUserID, Email, Password, fkUserGroupID FROM tbluser WHERE Email = "a" AND Password = "a"';
// Prepare the SQL statement.
$stmt = $conn->prepare($sql);
// Add the value to the SQL statement
$stmt->bindParam(':email', $email, PDO::PARAM_STR);
$stmt->bindParam(':password', $password, PDO::PARAM_STR);
// Execute SQL
$stmt->execute();
// Get the data in the result object
$result = $stmt->fetchAll(); // $result is NULL always...
// echo $stmt->rowCount(); // rowCount is always ZERO....
// Check that we have some data
if ($result != null)
{
// Start session
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
// Search the results
foreach($result as $row){
// Set global environment variables with the key fields required
$_SESSION['UserID'] = $row['pkUserID'];
$_SESSION['Email'] = $row['Email'];
}
echo 'yippee';
// Return empty string
return '';
}
else {
// Failed login
return 'Login unsuccessful!';
}
$conn = null;
}
catch (PDOexception $e)
{
return 'Login failed: ' . $e->getMessage();
}
}
?>
the connect code is;
<?php
$servername = 'localhost';
$username = 'admin';
$password = 'password';
try {
// Change this line to connect to different database
// Also enable the extension in the php.ini for new database engine.
$conn = new PDO('mysql:host=localhost;dbname=database', $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// echo 'Connected successfully';
}
catch(PDOException $e)
{
echo 'Connection failed: ' . $e->getMessage();
}
?>
I'm connecting to mySQL. Thanks for the help,
Jim
It was a simple but stupid error.
I had a variable called $password also in the connect.php file which was overwriting the $password that I was passing to the checklogin.
Jim
I'm getting a Call to a member function prepare() on a non-object error in my PHP when using PDO to select data that was sent via an AJAX call.
Searching around on StackOverflow I've found many answers to this error, but none work to fix my problem.
The weird part is that the other PHP files use the same PDO calls and work successfully, but this one is giving me the non-object error only.
To note, the PDO connection is identical to the other pages where it works, so I know that's not causing the problem.
Also, I have tested that the AJAX data sent is being received, and that is working too.
PHP Code
$mysql_user = "NotTelling";
$mysql_password = "DefinatelyNotThis";
try
{
$dbh = new PDO("mysql:host=somehost;dbname=somename", $mysql_user, $mysql_password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$username = $_POST['username'];
$inPword = $_POST['password'];
$lat = $_POST['lat'];
$lon = $_POST['lon'];
$loggedin = "";
$password_hash = "";
$loggedinstatus = "";
$pts = "";
function getLoginInfo()
{
$sth = $dbh -> prepare('SELECT pword, loggedin, points FROM login WHERE uname = :uname');
$sth->bindParam(':uname', $username, PDO::PARAM_STR);
while($row = $sth->fetch(PDO::FETCH_ASSOC))
{
echo $row['pword'];
echo $row['loggedin'];
echo $row['points'];
}
$password_hash = $fetch['pword'];
$loggedinstatus = $fetch['loggedin'];
$pts = $fetch["points"];
if($password_hash === null || $loggedinstatus === null || $pts === null)
{
die(json_encode(array("message" => "none")));
}
else
{
return "more";
}
}
function checkLoginCreds()
{
if(crypt($inPword, $password_hash) === $password_hash)
{
switch($loggedinstatus)
{
case "no":
$sel = $dbh->prepare("UPDATE login SET loggedin='yes' WHERE uname = ?");
$sel->execute(array($username));
return "AllGood";
break;
defaut:
return "alreadyin";
break;
}
}
else
{
return "BadLogin";
}
}
if(getLoginInfo() === "more")
{
echo json_encode(array("message" => checkLoginCreds()));
}
getLoginInfo();
}
catch(PDOException $e)
{
echo $e->getMessage();
file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
}
Finally, here's the output when I var_dump() the PDO connection.
object(PDO)#1 (0) {}
For this to work, you need to use the global variable scope, explained here: http://php.net/manual/en/language.variables.scope.php
$mysql_user = "NotTelling";
$mysql_password = "DefinatelyNotThis";
try
{
$dbh = new PDO("mysql:host=somehost;dbname=somename", $mysql_user, $mysql_password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$username = $_POST['username'];
$inPword = $_POST['password'];
$lat = $_POST['lat'];
$lon = $_POST['lon'];
$loggedin = "";
$password_hash = "";
$loggedinstatus = "";
$pts = "";
function getLoginInfo()
{
global $dbh, $username, $password_hash, $loggedinstatus, $pts;
$sth = $dbh -> prepare('SELECT pword, loggedin, points FROM login WHERE uname = :uname');
$sth->bindParam(':uname', $username, PDO::PARAM_STR);
while($row = $sth->fetch(PDO::FETCH_ASSOC))
{
echo $row['pword'];
echo $row['loggedin'];
echo $row['points'];
}
$password_hash = $fetch['pword'];
$loggedinstatus = $fetch['loggedin'];
$pts = $fetch["points"];
if($password_hash === null || $loggedinstatus === null || $pts === null)
{
die(json_encode(array("message" => "none")));
}
else
{
return "more";
}
}
function checkLoginCreds()
{
global $dbh, $inPword, $password_hash, $loggedinstatus, $username;
if(crypt($inPword, $password_hash) === $password_hash)
{
switch($loggedinstatus)
{
case "no":
$sel = $dbh->prepare("UPDATE login SET loggedin='yes' WHERE uname = ?");
$sel->execute(array($username));
return "AllGood";
break;
defaut:
return "alreadyin";
break;
}
}
else
{
return "BadLogin";
}
}
if(getLoginInfo() === "more")
{
echo json_encode(array("message" => checkLoginCreds()));
}
getLoginInfo();
}
catch(PDOException $e)
{
echo $e->getMessage();
file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
}
But this can get messy very quickly.
I suggest you put the variables in an array or using OOP for a more robust solution: http://php.net/manual/en/language.oop5.php
This is how you can define it in a class..
class someClass {
private $db;
public function __construct(){
$this->dbconnect();
}
private function dbconnect() {
try { //try connection
$dbh = new PDO('mysql:host=localhost;dbname=somenane', 'usernane', 'pass');
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->dbh = $dbh;
} catch (Exception $e) { //connection failed
die("Oh no! It seems we took too long to respond");
}
}
public function getLoginInfo() {
$sth = $this->dbh->prepare('SELECT pword, loggedin, points FROM login WHERE uname = :uname');
$sth->bindParam(':uname', $username, PDO::PARAM_STR);
//cont the code
}
}
Not sure if it's good enough..but it will work..
I'm trying out the PDO extension, and was wondering if it were possible to store the opening of the DB connection as a function that could be called whenever needed. I tried some basic stuff, but it doesn't seem to work. Can it?
Example Function
function DB() {
$conn = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if (!$conn) {
echo "<br />MySQL SERVER CONNECTION ERROR.<br />\n";
}
if($conn) {
return $conn;
}
}
Example Useage
function is_post_id($submitted) {
try {
$id = $submitted;
DB();
//check to see if there is a post
//with an id matching the submitted query
$qPOST= $conn->prepare('SELECT COUNT(*) FROM posts WHERE id = :id');
$qPOST->execute(array('id' => $id));
//results counted
$cPOST= (int)$qPOST->fetchColumn();
if($cPOST > 0) {
return TRUE;
}
else {
return FALSE;
}
} catch(PDOException $e) {
echo $e->getMessage();
}
}
call it as :
$conn = $this->DB();
OR
$conn = $className->DB();