This is a snapshot of the code I am struggling with in php. I have a database object, an activity class and a booking form. From the booking form I pass three variables to the check availability method which queries the database. The var dump is returning:
object(DB)#3 (6) { ["_pdo":"DB":private]=> object(PDO)#4 (0) { } ["_query":"DB":private]=>
object(PDOStatement)#6 (1) { ["queryString"]=> string(99) "SELECT * FROM `activity` WHERE name =
'Archery' AND act_date = '05/01/2015' AND time_from = '10.00'" } ["_error":"DB":private]=>
bool(false) ["_results":"DB":private]=> array(0) { } ["_count":"DB":private]=> int(0)
["_data":"DB":private]=> NULL }
This makes me think that the query is not returning something yet the query does return records in MySQL. Any help would be greatly appreciated.
1. Calling method to check availability:
if($activity->checkDateTimeAvailability($act_name, $date, $time) === false)){
// Do something here
}
//Method to check if the activity is available at the requested date and time:
public function checkDateTimeAvailability($name, $date, $time) {
$result = $this->_db->query("SELECT * FROM `activity` WHERE name =
'$name' AND act_date = '$date' AND time_from = '$time'");
if(!empty($result)){
echo "query successful";
var_dump($result);
return true;
} else {
return false;
}
}
//Generic query method:
public function query($sql, $params = array()) {
// reset to ensure an error from a previous query is not returned.
$this->_error = false;
if($this->_query = $this->_pdo->prepare($sql)) {
$x = 1;
if(count($params)) {
foreach($params as $param) {
$this->_query->bindValue($x, $param);
$x++;
}
}
if($this->_query->execute()) {
$this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
$this->_count = $this->_query->rowCount();
} else {
$this->_error = true;
}
}
return $this;
}
First of all, NEVER use variables in a SQL query, use prepare statements.
To you question. The PDO::query method returns a PDOStatement object. With this object you can fetch the result from the database server.
Just call $this->_db->query('Your SQL query')->fetchAll() and you get your rows.
Related
I am trying to use the following Query method in my db class to query the database with a prepared statement. The SQL appears to work fine in MySQL but in the prepared statement only works when there is one condition after the where but I need it to work with three conditions. Any help would be greatly appreciated.
DB Class - Query Method
// Generic query method.
public function query($sql, $params = array()) {
// reset to ensure an error from a previous query is not returned.
$this->_error = false;
if($this->_query = $this->_pdo->prepare($sql)) {
$x = 1;
if(count($params)) {
foreach($params as $param) {
$this->_query->bindValue($x, $param);
$x++;
}
}
if($this->_query->execute()) {
$this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
$this->_count = $this->_query->rowCount();
} else {
$this->_error = true;
}
}
return $this;
}
// Calling query method
// Method to check if the activity is available at the requested date and time.
public function checkDateTimeAvailability($name, $date, $time) {
$result = $this->_db->query("SELECT * FROM `activity` WHERE name = ? AND act_date = ? AND
time_from = ?", array($name, $date, $time));
var_dump($result);
if(!empty($result)){
echo "query successful";
return true;
} else {
return false;
}
}
I'm newbie in PHP and WordPress. This approach was working fine for me in ASP.NET but here both queries are not working. When I comment the first one, the second one(Insertion) is working fine.
$dbhostname="111.1.11.111";
$dbusername="db_userName";
$dbpassword="mypassword";
$con=mysqli_connect($dbhostname,$dbusername,$dbpassword,"db_name");
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
Check wether the email exists or not ?
$sql="CALL Select_ConfirmEmailExistance('abc#abc.com')";
$containsResult=0;
if ($result=mysqli_query($con,$sql))
{
// Get field information for all fields
while ($fieldinfo=mysqli_fetch_assoc($result))
{
if (isset($fieldinfo)) {
$containsResult=1;// Email Exists
}
}
mysqli_free_result($result);
if ($containsResult==0) { // In case email does not exists enter it.
$sql="CALL insert_Userinfo('abc','def','abc#abc.com','mnop')";
if ($result=mysqli_query($con,$sql))
{
$data;
while ($fieldinfo=mysqli_fetch_assoc($result))
{
$data[]=$fieldinfo;
}
}
}
print_r($data);
}
mysqli_close($con);
First Store Procdure
BEGIN
SELECT 1 as emailstatus FROM userinfo WHERE email= p_email;
END
Second Stored Procedure
INSERT INTO `userinfo` (
`first_name`,
`last_name`,
`email`,
`password`
)
VALUES
(
`FName`,
`LName`,
`Email`,
`Pass`
);
SELECT
user_id
FROM
userinfo
ORDER BY
user_id DESC
LIMIT 1;
Here is what I was talking about when I said create a query class to fetch data. This is just a simple one, but it works pretty effectively and you can build it out to be pretty powerful.
class DBEngine
{
public $con;
public function __construct($host="111.1.11.111",$db = "dbname",$user="db_userName",$pass="mypassword")
{
try {
$this->con = new PDO("mysql:host=$host;dbname=$db",$user,$pass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
}
catch (Exception $e) {
return 0;
}
}
// Simple fetch and return method
public function Fetch($_sql)
{
$query = $this->con->prepare($_sql);
$query->execute();
if($query->rowCount() > 0) {
while($rows = $query->fetch(PDO::FETCH_ASSOC)) {
$array[] = $rows;
}
}
return (isset($array) && $array !== 0 && !empty($array))? $array: 0;
}
// Simple write to db method
public function Write($_sql)
{
$query = $this->con->prepare($_sql);
$query->execute();
}
}
// Create an instance of the engine
$query = new DBEngine();
// Query 1 will return an array or false (0)
$call1 = $query->Fetch("CALL Select_ConfirmEmailExistance('abc#abc.com')");
// Assign your true/false
$containsResult = ($call1 !== 0)? 1:0;
// Run second query and return array or false (0)
if($containsResult == 0)
$data = $query->Fetch("CALL insert_Userinfo('abc','def','abc#abc.com','mnop')");
// Display returned result
print_r($data);
It is quite simple. Your code is fine but you only have to create two separete functions and simply call those functions instead of the code directly.
I am running 2 queries, the first one goes through correctly and returns the desired value, but the second one returns false.
I have set $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); so I should be getting an exception over false, so I am guessing that my $stmt->execute(); is the culprit here.
As that's the only function that can return false now that I've set the error attribute.
I have also tried setting $stmt->closeCursor();, $stmt = null;, and unset($stmt); with no avail.
This executes two queries (both "darkrp" and "pointshop" in the fetch_wallet() function.
if($this->pdo) {
foreach($this->methods as $method => $bool) {
if($bool) { $array[$method] = $this->fetch_wallet($method); }
}
}
This is the fetch_wallet() function:
public function fetch_wallet($type) {
if($type == "darkrp") {
$query = "SELECT `wallet` FROM `darkrp_player` WHERE uid=:uid LIMIT 1";
}
elseif ($type == "pointshop") {
$query = "SELECT `points` FROM `pointshop_data` WHERE uniqueid=:uid LIMIT 1";
}
try {
$stmt = $this->pdo->prepare($query);
$stmt->execute(array(":uid" => $this->uniqueid));
$result = $stmt->fetchColumn();
return $result;
}
catch (PDOException $e) {
return $e->getMessage();
}
}
When I run var_dump($stmt->errorInfo()); I get this, which means that both queries runs fine, although the last one returns false when it should return 440. No exception is thrown.
array(3) {
[0]=> string(5) "00000"
[1]=> NULL
[2]=> NULL
}
array(3) {
[0]=> string(5) "00000"
[1]=> NULL
[2]=> NULL
}
Printed screen of the pointshop_data table in phpMyAdmin (I want the 440 value there):
Value returned from var_dump($this->uniqueid); is 3266928646
I have debugged everything, and I get no errors whatsoever, just a false.
PHP Version: 5.3.10
MySQL Version: 5.5.38
OS: Ubuntu 12.04 LTS
I think there must be some other error in your class that makes this code does not work.
I've imported your tables structure and created the following testing code:
<?php
class A
{
private $pdo;
private $uniqueid;
private $methods = ['darkrp' => true, 'pointshop' => true];
public function __construct($pdo, $uniqueid)
{
$this->pdo = $pdo;
$this->uniqueid = $uniqueid;
}
public function fetch_wallet($type)
{
if ($type == "darkrp") {
$query = "SELECT `wallet` FROM `darkrp_player` WHERE uid=:uid LIMIT 1";
} elseif ($type == "pointshop") {
$query = "SELECT `points` FROM `pointshop_data` WHERE uniqueid=:uid LIMIT 1";
}
try {
$stmt = $this->pdo->prepare($query);
$stmt->execute(array(":uid" => $this->uniqueid));
$result = $stmt->fetchColumn();
return $result;
} catch (PDOException $e) {
return $e->getMessage();
}
}
public function run()
{
if ($this->pdo) {
foreach ($this->methods as $method => $bool) {
if ($bool) {
$array[$method] = $this->fetch_wallet($method);
var_dump($array[$method]);
}
}
}
}
}
$pdo = new PDO('mysql:host=localhost;dbname=tests', 'root', '');
$a = new A($pdo, 3266928646);
$a->run();
The result I get for this is:
string(4) "2075" string(3) "440"
So it is working as it should.
Please try this code (that's the whole file - of course you need to change your db name, user and password) and check if it gets you the same results. If yes, probably you have other errors in your class.
Change
$stmt->execute(array(":uid" => $this->uniqueid));
to
$stmt->bindValue(':uid', $this->uniqueid);
$stmt->execute();
I seem to have problem getting affected_rows when I INSERT and SELECT, it just returns -1 for some reason? I'm using a database class which I use all the time for my projects which uses MYSQLI prepare statements to avoid SQL injections.
Does anyone know why it returns -1 all the time? From what I have read it should be able to return affected rows on both INSERT and SELECT.
Database class
class database {
protected $_mysqli;
protected $_debug;
public function __construct($host, $username, $password, $database, $debug) {
$this->_mysqli = new mysqli($host, $username, $password, $database);
$this->_debug = (bool) $debug;
if (mysqli_connect_errno()) {
if ($this->_debug) {
echo mysqli_connect_error();
debug_print_backtrace();
}
return false;
}
return true;
}
public function q($query) {
if ($query = $this->_mysqli->prepare($query)) {
if (func_num_args() > 1) {
$x = func_get_args();
$args = array_merge(array(func_get_arg(1)),
array_slice($x, 2));
$args_ref = array();
foreach($args as $k => &$arg) {
$args_ref[$k] = &$arg;
}
call_user_func_array(array($query, 'bind_param'), $args_ref);
}
$query->execute();
if ($query->errno) {
if ($this->_debug) {
echo mysqli_error($this->_mysqli);
debug_print_backtrace();
}
return false;
}
if ($query->affected_rows > -1) {
return $query->affected_rows;
}
$params = array();
$meta = $query->result_metadata();
while ($field = $meta->fetch_field()) {
$params[] = &$row[$field->name];
}
call_user_func_array(array($query, 'bind_result'), $params);
$result = array();
while ($query->fetch()) {
$r = array();
foreach ($row as $key => $val) {
$r[$key] = $val;
}
$result[] = $r;
}
$query->close();
return $result;
} else {
if ($this->_debug) {
echo $this->_mysqli->error;
debug_print_backtrace();
}
return false;
}
}
public function handle() {
return $this->_mysqli;
}
public function last_insert_id()
{
return $this->_mysqli->insert_id;
}
public function found_rowss()
{
return $this->_mysqli->affected_rows;
}
}
for Select-statements created with prepare you should use $query->num_rows() or mysqli_stmt_num_rows($query).
The Insert-Statement may give you supressed errors when you do a "INSERT IGNORE" which may lead to the -1 in $query->affected_rows().
A comment on php.net (second link) suggests you use $query->sqlstate=="00000" to check for errors.
see php.net (manual/en/mysqli-stmt.affected-rows):
"This function only works with queries which update a table. In order to get the number of rows from a SELECT query, use mysqli_stmt_num_rows() instead."
and php.net (manual/en/mysqli.affected-rows):
"Checking if mysqli->affected_rows will equal -1 or not is not a good method of determining success of "INSERT IGNORE" statements. Example: Ignoring duplicate key errors while inserting some rows containing data provided by user only if they will match specified unique constraint causes returning of -1 value by mysqli->affected_rows even if rows were inserted. (checked on MySQL 5.0.85 linux and php 5.2.9-2 windows). However mysqli->sqlstate returns no error if statement was executed successfully."
I have been using the old mysql api in PHP for a long time and want to start using mysqli for both speed and security with a new project I'm working on. I've looked through the manual and read several tutorials, but I'm finding a lot of conflicting and somewhat confusing information on how to do prepared statements in mysql.
Is there anything in this code that doesn't need to be there, and is there anything that is missing? Also, is this the easiest way to do something simple like this (seems somewhat involved for such a simple task)?
Procedural:
// build prepared statement
$query = mysqli_prepare($link, "SELECT email FROM users WHERE id = ?");
// bind parameters to statement
mysqli_stmt_bind_param($query, 's', $_GET['id']);
// execute statement
mysqli_stmt_execute($query);
// bind the variables to the result
mysqli_stmt_bind_result($query, $email);
// print the results
while (mysqli_stmt_fetch($query)) {
echo $email;
}
// close the statement
mysqli_stmt_close($query);
// close connection
mysqli_close($link);
Object-Oriented:
// build prepared statement
$query = $link->prepare("SELECT email FROM users WHERE id = ?");
// bind parameters to statement
$query->bind_param('s', $_GET['id']);
// execute statement
$query->execute();
// bind the variables to the result
$query->bind_result($email);
// print the results
while ($query->fetch()) {
echo $email;
}
// close the statement
$query->close();
// close connection
$link->close();
Here's the guts of a semi-self-explanatory class that encapsulates mysqli, including prepared statements, which are quite tricky. It's pretty well tested - I've been using it for a year now without change.
It only implements prepared statements to Execute SQL commands because they change data and often require nasty encoding tricks otherwise. If you want SELECTs, it's left as an exercise for the reader - it's easier. :)
<?php
class Db
{
var $_mysqli;
var $_result;
var $_error_msg;
public function __construct($server, $user, $password, $name)
{
$this->_mysqli = new mysqli("p:".$server, $user,
$password, $name);
if($this->_mysqli->connect_errno)
{
$this->_error_msg = $this->_mysqli->connect_error;
}
}
public function __destruct()
{
}
private function sql_select($sql)
{
$this->_mysqli->query("SET NAMES 'utf8'"); // a little help for UTF8 io
$this->_result = $this->_mysqli->query($sql);
}
private function sql_close()
{
$this->_mysqli->close();
}
public function ErrorMessage()
{
return $this->_error_msg;
}
public function SqlRows($sql)
{
$rows = array();
$result = $this->sql_select($sql);
if($this->IsError())
{
return $rows;
}
while($row = $result->fetch_array())
{
$rows[] = $row;
}
$result->free();
return $rows;
}
public function SqlObjects($sql)
{
$objects = array();
$result = $this->sql_select($sql);
while($object = $this->_result->fetch_object())
{
$objects[] = $object;
}
$result->free();
return $objects;
}
public function SqlOneObject($sql)
{
$result = $this->sql_select($sql);
$obj = $result->fetch_object();
$result->free();
return $obj;
}
public function SqlOneRow($sql)
{
$result = $this->sql_select($sql);
if(! is_object($result))
return null;
if($result->num_rows > 0)
$row = $result->fetch_array();
else
$row = null;
$result->free();
return $row;
}
public function SqlOneValue($sql)
{
$result = $this->sql_select($sql);
if(!empty($result))
{
$row = $result->fetch_array();
}
$result->free();
return empty($row) ? null : $row[0] ;
}
// returns number of affected rows
public function SqlExecute($sql)
{
$this->_result = $this->_mysqli->query($sql);
return $this->affected_rows();
}
private function affected_rows()
{
return $this->_mysqli->affected_rows;
}
private function IsError()
{
if(empty($this->_mysqli))
return false;
return !empty($this->_mysqli->error);
}
// arguments are sql and an array of
// argument references (not values).
public function SqlExecutePS($sql, $args)
{
$stmt = $this->_mysqli->prepare($sql);
// make the type-string
$typestr = make_typestring($args);
$params = array($typestr);
$params = array_merge($params, $args);
call_user_func_array(array($stmt, 'bind_param'), $params);
$stmt->execute();
$ret = $this->affected_rows();
$stmt->close();
return $ret;
}
public function SqlExists($sql)
{
$result = $this->SqlOneRow($sql);
return !empty($result[0]);
}
function make_typestring($args)
{
assert(is_array($args));
$ret = "";
foreach($args as $arg)
{
switch(gettype($arg))
{
case "boolean":
case "integer":
$ret .= "i";
break;
case "double":
$ret .= "d";
break;
case "string":
$ret .= "s";
break;
case "array":
case "object":
case "resource":
case "NULL":
default:
// call it a blob and hope
// you know what you're doing.
$ret .= "b";
break;
}
}
return $ret;
}
}
?>