php PDO - How do I get last inserted Id? - php

i was trying to get parent_id which is the last_insert_id. I am using php PDO, i was trying to get lastinsertedId but it keeps gave me an error.
I am able to execute parentRegister but i cannot get the lastInsertId using PDO.
What's wrong on my code?
function connect() {
// connection template
// $pdo = new PDO('mysql:host=127.0.0.1;dbname=SocialNetwork;charset=utf8','root','');
global $host;
global $dbName;
global $dbusername;
global $dbpassword;
try {
$pdo = new PDO("mysql:host=".$host.";dbname=".$dbName."", $dbusername, $dbpassword);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); // fetch as associative
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); // fetch as object
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
return $pdo;
} catch (PDOException $e) {
// die('error message: '.$e->message().'<br>');
// die('Our system have some problems now. Please try again later');
return false;
}
}
function query($query, $params = array()) {
$stmt = connect()->prepare($query);
$stmt->execute($params);
if(explode(' ', $query)[0] == 'SELECT'){
$data = $stmt->fetchAll();
return $data;
}
}
// parents 7 column
$parentsData = array(
'role_id' => 2,
'email' => $submittedData['email'],
'parent_name' => $submittedData['parentName'],
'phone' => $submittedData['phone'],
'address' => $submittedData['address'],
'postcode' => $submittedData['postcode'],
'password' => $submittedData['password']
);
// swimmers 6 column
$swimmersData = array(
'role_id' => 3,
'username' => $submittedData['username'],
'password' => $submittedData['password'],
'fname' => $submittedData['fname'],
'lname' => $submittedData['lname'],
'dob' => $submittedData['dob']
);
$parentsRegister = query('INSERT INTO parents('.$parentsField.') VALUES ('.$parentsValue.')', $parentsData);
$swimmersRegister = query('INSERT INTO swimmers('.$swimmersField.',`parent_id`) VALUES ('.$swimmersValue.','.connect()->query("SELECT LAST_INSERT_ID()")->fetchColumn().')', $swimmersData);
I tried to use this code but keeps gave me 0
$stmt = connect()->lastInsertId();
echo $stmt;

just figured out $pdo need to be set as global variable.
// put pdo variable as global to handle last inserted id
$pdo;
function connect() {
global $host;
global $dbName;
global $dbusername;
global $dbpassword;
global $pdo;
try {
$pdo = new PDO("mysql:host=".$host.";dbname=".$dbName."", $dbusername, $dbpassword);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); // fetch as associative
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); // fetch as object
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
return $pdo;
} catch (PDOException $e) {
// die('error message: '.$e->message().'<br>');
// die('Our system have some problems now. Please try again later');
return false;
}
}
function query($query, $params = array()) {
$stmt = connect()->prepare($query);
$stmt->execute($params);
// if select
if(explode(' ', $query)[0] == 'SELECT'){
$data = $stmt->fetchAll();
return $data;
// otherwise (update, delete, insert)
} else {
return ($stmt) ? true : false;
}
}
// insert to database
$parentsRegister = query('INSERT INTO parents('.$parentsField.') VALUES ('.$parentsValue.')', $parentsData);
$swimmersRegister = query('INSERT INTO swimmers('.$swimmersField.',`parent_id`) VALUES ('.$swimmersValue.','.$pdo->lastInsertId().')', $swimmersData);

Related

Unable to get error info with PDO in PHP

I am in the process of learning PDO and am trying to implement it in my current project. When I used mysqli, I could get detailed info about any error using mysqli_error($connection). I googled at what the comparable for PDO would be and found this post, and decided to implement it in my code. However, I am unable to get any error messages even when I know there is an obvious error in the sql statement.
Relevant code:
class Database {
public $connection;
function __construct() {
$this->open_database_connection();
}
public function open_database_connection() {
try {
$this->connection = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PASSWORD);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->connection->setAttribute( PDO::ATTR_EMULATE_PREPARES, false);
} catch(PDOException $e) {
echo $e->getMessage();
die('Could not connect');
}
} // end of open_database_connection method
public function query($sql, $params = []) {
try {
$query = $this->connection->prepare($sql);
} catch (Exception $e) {
var_dump('mysql error: ' . $e->getMessage());
}
foreach($params as $key => $value) {
if ($key === ':limit') {
$query->bindValue($key, $value, PDO::PARAM_INT);
} else {
$query -> bindValue($key, $value);
}
}
try {
$query->execute();
} catch(Exception $e) {
echo 'Exception -> ';
var_dump($e->getMessage());
}
/*
DID NOT WORK:
if (!$query->execute()) {
print_r($query->errorinfo());
}*/
$result = $query->fetchAll(PDO::FETCH_ASSOC);
$this->confirm_query($result);
return $result;
} // end of query method
function confirm_query($query) {
if (!$query) {
die('mysql error: ');
}
}
When I run the code, I do get the "mysql error", but I do not get any details about it. What am I doing wrong?
Update: As requested, I am providing additional details below.
What I am trying to do is get the user's login detail to be verified. To that end, once the user inputs his credentials , this code runs:
if (isset($_POST['submit'])) {
$username = trim($_POST['username']);
$password = trim($_POST['password']);
//check the database for the user
$user_found = User::verify_user($username, $password);
Relevant code from the User class:
public static function verify_user($username, $password) {
global $db;
$username = $db->escape_string($username);
$password = $db->escape_string($password);
$values = [ ":username" => $username,
":password" => $password,
":limit" => 1
];
$result_array = self::find_this_query("SELECT * FROM users WHERE username=:username AND password=:password LIMIT :limit", true, $values);
return !empty($result_array)? array_shift($result_array) : false;
}
public static function find_this_query($sql, $prepared = false, $params = []) {
global $db;
$the_object_array = array();
$result = $db->query($sql, $params);
$arr_length = count($result);
for ($i = 0; $i < $arr_length; $i++) {
$the_object_array[] = self::instantiation($result[$i]);
}
return $the_object_array;
}
public static function instantiation($the_record) {
$the_object =new self; //we need new self because $the_record corresponds to one user!
foreach($the_record as $the_attribute => $value) {
if ($the_object->has_the_attribute($the_attribute)) {
$the_object->$the_attribute = $value;
}
}
return $the_object;
}
public function has_the_attribute($attribute) {
$object_properties = get_object_vars($this);
return array_key_exists($attribute, $object_properties);
}
You have to use PDO::errorInfo():
(...)
public function query($sql, $params = []) {
try {
$query = $this->connection->prepare($sql);
if( !$query )
{
$error = $this->connection->errorInfo();
die( "mysql error: {$error[2]}" );
}
} catch (Exception $e) {
var_dump('mysql error: ' . $e->getMessage());
}
(...)
}
PDO::errorInfo returns an array:
Element 0: SQLSTATE error code (a five characters alphanumeric identifier defined in the ANSI SQL standard);
Element 1: Driver-specific error code;
Element 2: Driver-specific error message.

get row count in pdo class - after fetching data

this is my pdo class
<?php
class Database
{
protected $dbh;
protected $query;
public $rows;
public function __construct($host,$user,$pass,$dbname)
{
// Set DSN
$dsn = 'mysql:host=' . $host . ';dbname=' . $dbname;
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create a new PDO instanace
try
{
$this->dbh = new PDO($dsn, $user, $pass, $options);
}
catch(PDOException $e)
{
echo $this->error = $e->getMessage();
die();
}
}
public function query($query)
{
$this->query = $this->dbh->query($query);
}
public function fetchAllQuery()
{
return $this->query->fetchAll(PDO::FETCH_ASSOC);
}
public function rowCountQuery()//--------------------------------(1)
{
//for get all the rows when query execute
$arr = $this->fetchAllQuery()
$this->rows = count($arr);
}
}
$database = new Database('localhost','root','','speed');
$area='aa';
$price=200;
$query = $database->query("SELECT * FROM tbl_deliverygrid");
$result = $database->fetchAllQuery();///-------------------------------(2)
echo '<pre>',print_r($result),'</pre><br>';
echo 'row count query [['.count($result).']]<br>';
$database->rowCountQuery();//---------------calling (1)
echo '['.print_r($database->rows).']';
echo '<br>';
i want to get row count of a query
for that instead of using rowCount() method i use fetch all the rows to variable as a array and then count the elements of that array
rowCountQuery method consist above functionality
but i cant get row count now??? method returns null output
but if i remove (2) i can get and echo the output from rowCountQuery method
corrrectly
i want to know how to get row count not removing (2)
<?php
class Database
{
protected $dbh;
protected $query;
public $rows;
protected $count;
public function __construct($host,$user,$pass,$dbname)
{
// Set DSN
$dsn = 'mysql:host=' . $host . ';dbname=' . $dbname;
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create a new PDO instanace
try
{
$this->dbh = new PDO($dsn, $user, $pass, $options);
}
catch(PDOException $e)
{
echo $this->error = $e->getMessage();
die();
}
}
public function query($query)
{
$this->query = $this->dbh->query($query);
}
public function fetchAllQuery()
{
$result = $this->query->fetchAll(PDO::FETCH_ASSOC);
$this->count = count($result);
return $result;
}
public function rowCountQuery()//--------------------------------(1)
{
return $this->count;
}
}
$database = new Database('localhost','root','','speed');
$area='aa';
$price=200;
$query = $database->query("SELECT * FROM tbl_deliverygrid");
$result = $database->fetchAllQuery();///-------------------------------(2)
echo '<pre>',print_r($result),'</pre><br>';
echo 'row count query [['.count($result).']]<br>';
echo '['.print_r($database->rowCountQuery()).']';
echo '<br>';
You are consecutively fetching a result set twice in the same script, which will result in a null result for the 2nd request. Since you already have the result set after (2), you can execute count() on $result.

Fatal error: Call to a member function execute() on null [duplicate]

This question already has answers here:
Reference - What does this error mean in PHP?
(38 answers)
Closed 2 years ago.
I keep getting the following error:
Fatal error: Call to a member function execute() on null in /home/[sitename]/public_html/fc/includes/class_db_handle.php on line 130
This is from the u-Auctions script and I honestly am extremely noob to PDO
please help in "DUMMIE TERMS".
if (!defined('InuAuctions')) exit('Access denied');
class db_handle
{
// database
private $pdo;
private $DBPrefix;
private $CHARSET;
private $lastquery;
private $fetchquery;
private $error;
public $PDOerror;
public function connect($DbHost, $DbUser, $DbPassword, $DbDatabase, $DBPrefix, $CHARSET)
{
$this->DBPrefix = $DBPrefix;
$this->CHARSET = $CHARSET;
try {
// MySQL with PDO_MYSQL
$this->pdo = new PDO("mysql:host=$DbHost;dbname=$DbDatabase;charset =$CHARSET", $DbUser, $DbPassword);
// set error reporting up
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// actually use prepared statements
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e) {
$this->trigger_error($e->getMessage());
}
}
// to run a direct query
public function direct_query($query)
{
try {
$this->lastquery = $this->pdo->query($query);
}
catch(PDOException $e) {
$this->trigger_error($e->getMessage());
}
}
// put together the quert ready for running
/*
$query must be given like SELECT * FROM table WHERE this = :that AND where = :here
then $params would holds the values for :that and :here, $table would hold the vlue for :table
$params = array(
array(':that', 'that value', PDO::PARAM_STR),
array(':here', 'here value', PDO::PARAM_INT),
);
last value can be left blank more info http://php.net/manual/en/pdostatement.bindparam.php
*/
public function query($query, $params = array())
{
try {
//$query = $this->build_query($query, $table);
$params = $this->build_params($params);
$params = $this->clean_params($query, $params);
$this->lastquery = $this->pdo->prepare($query);
//$this->lastquery->bindParam(':table', $this->DBPrefix . $table, PDO::PARAM_STR); // must always be set
foreach ($params as $val)
{
$this->lastquery->bindParam($val[0], $val[1], #$val[2], #$val[3], #$val[4]);
}
$this->lasta->execute();
//$this->lastquery->debugDumpParams();
}
catch(PDOException $e) {
//$this->lastquery->debugDumpParams();
$this->trigger_error($e->getMessage());
}
//$this->lastquery->rowCount(); // rows affected
}
// put together the quert ready for running
public function fetch($method = 'FETCH_ASSOC')
{
try {
// set fetchquery
if ($this->fetchquery == NULL)
{
$this->fetchquery = $this->lastquery;
}
if ($method == 'FETCH_ASSOC') $result = $this->fetchquery->fetch(PDO::FETCH_ASSOC);
if ($method == 'FETCH_BOTH') $result = $this->fetchquery->fetch(PDO::FETCH_BOTH);
if ($method == 'FETCH_NUM') $result = $this->fetchquery->fetch(PDO::FETCH_NUM);
// clear fetch query
if ($result == false)
{
$this->fetchquery = NULL;
}
return $result;
}
catch(PDOException $e) {
$this->trigger_error($e->getMessage());
}
}
// put together the quert ready for running + get all results
public function fetchall($method = 'FETCH_ASSOC')
{
try {
// set fetchquery
if ($this->fetchquery == NULL)
{
$this->fetchquery = $this->lastquery;
}
if ($method == 'FETCH_ASSOC') $result = $this->fetchquery->fetchAll(PDO::FETCH_ASSOC);
if ($method == 'FETCH_BOTH') $result = $this->fetchquery->fetchAll(PDO::FETCH_BOTH);
if ($method == 'FETCH_NUM') $result = $this->fetchquery->fetchAll(PDO::FETCH_NUM);
// clear fetch query
if ($result == false)
{
$this->fetchquery = NULL;
}
return $result;
}
catch(PDOException $e) {
$this->trigger_error($e->getMessage());
}
}
public function result($column = NULL)
{
$data = $this->lastquery->fetch(PDO::FETCH_BOTH);
if (empty($column) || $column == NULL)
{
return $data;
}
else
{
return $data[$column];
}
}
public function numrows()
{
try {
return $this->lastquery->rowCount();
}
catch(PDOException $e) {
$this->trigger_error($e->getMessage());
}
}
public function lastInsertId()
{
try {
return $this->pdo->lastInsertId();
}
catch(PDOException $e) {
$this->trigger_error($e->getMessage());
}
}
private function clean_params($query, $params)
{
// find the vars set in the query
preg_match_all("(:[a-zA-Z_]+)", $query, $set_params);
//print_r("params" . $query);
//print_r($params);
//print_r("set_params");
//print_r($set_params);
$new_params = array();
foreach ($set_params[0] as $val)
{
$key = $this->find_key($params, $val);
$new_params[] = $params[$key];
}
//print_r("new_params");
//print_r($new_params);
return $new_params;
}
private function find_key($params, $val)
{
foreach ($params as $k => $v)
{
if ($v[0] == $val)
return $k;
}
}
private function build_params($params)
{
$PDO_constants = array(
'int' => PDO::PARAM_INT,
'str' => PDO::PARAM_STR,
'bool' => PDO::PARAM_BOOL,
'float' => PDO::PARAM_STR
);
// set PDO values to params
for ($i = 0; $i < count($params); $i++)
{
// force float
if ($params[$i][2] == 'float')
{
$params[$i][1] = floatval($params[$i][1]);
}
$params[$i][2] = $PDO_constants[$params[$i][2]];
}
return $params;
}
private function trigger_error($error)
{
// DO SOMETHING
//$this->error = $error;
$this->PDOerror = $error;
}
// close everything down
public function __destruct()
{
// close database connection
$this->pdo = null;
}
}
You call $this->lasta->execute(); but you have no field lasta
Try this
$this->lastquery->execute();
I would try extending the db_handle class and modifying/creating some methods like so:
<?php
// Make sure the db_handle is included and loaded before hand so it can be extended
class QueryEngine extends db_handle
{
private $bind;
public function connect($host, $username, $password, $database)
{
// One note, I removed:
// $this->DBPrefix = $DBPrefix;
// $this->CHARSET = $CHARSET;
// You can add those back in if you want
try {
// Create connection
$opts = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC);
$this->pdo = new PDO('mysql:host='.$host.';dbname='.$database, $username, $password,$opts);
}
catch(PDOException $e) {
die($e->getMessage());
}
}
public function query($query, $params = false)
{
if(!empty($params))
$this->bindVals($params);
try {
if(!empty($this->bind)) {
$this->lastquery = $this->pdo->prepare($query);
$this->lastquery->execute($this->bind);
}
else
$this->lastquery = $this->pdo->query($query);
}
catch(PDOException $e) {
die($e->getMessage());
}
return $this;
}
public function fetch()
{
while($row = $this->lastquery->fetch())
$result[] = $row;
return (!empty($result))? $result : 0;
}
private function bindVals($params = false)
{
$this->bind = false;
if(empty($params) || !is_array($params))
return $this;
$i = 0;
foreach($params as $values) {
$this->bind[':'.$i] = $values;
$i++;
}
return $this;
}
}
To use our new class:
$dbEngine = new QueryEngine();
$dbEngine->connect($host,$username,$password,$database);
print_r($dbEngine->query("select * from users where ID = :0",array("1"))->fetch());
This would give you something like (in my db obviously, the table and columns will be different for you):
Array
(
[0] => Array
(
[ID] => 1
[unique_id] => 20150203190700523616
[username] => tester
[password] => $2a$12$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[first_name] => Ras
[last_name] => Clatt
[email] => ras#clatt.com
[usergroup] => 3
[user_status] => on
[reset_password] => $2y$10$xxxxxxxxxxxxxxxxxxx
[timestamp] => 2015-09-25 08:35:09
)
)
This class library you are using is similar to mine so what I have added is parts of the class I use. I tested this extended class out and it works with my database, so hopefully it works with yours!

PDO - Iteratively Binding Variables

I am trying to create a function to iteratively bind variables. This is what I have so far:
function prepareQuery($db, $query, $args) {
// Returns a prepared statement
$stmt = $db->prepare($query);
foreach ($args as $arg => $value) {
$stmt->bindParam($arg, $value);
}
return $stmt;
}
This is how I'm using it:
$stmt = prepareQuery($db, "SELECT * FROM `Licenses` WHERE `verCode`=:verCode", Array(":verCode" => $verCode));
$verCode = "some_string";
$stmt->execute();
while ($info = $stmt->fetch()) {
print_r($info);
}
Though it doesn't print anything. I know the database entry exists, and the same query works from PHPMyAdmin. So, I think it's just a problem in how my function tries to create the bindings. How can I fix this? Thanks!
Do not create a function to iteratively bind variables. PDO can do it already
function prepareQuery($db, $query, $args) {
$stmt = $db->prepare($query);
$stmt->execute($args);
return $stmt;
}
If it doesn't print anything, then it didn't find anything. As simple as that.
You don't even need this prepare query function actually. Just amend PDO very little like this
class myPDOStatement extends PDOStatement
{
function execute($data = array())
{
parent::execute($data);
return $this;
}
}
$user = 'root';
$pass = '';
$dsn = 'mysql:charset=utf8;dbname=test;host=localhost';
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => TRUE,
PDO::ATTR_STATEMENT_CLASS => array('myPDOStatement'),
);
$pdo = new PDO($dsn, $user, $pass, $opt);
and you'll be able to write such a neat chain:
$sql = "SELECT * FROM `Licenses` WHERE `verCode`=:verCode";
$code = "some_string";
$data = $pdo->prepare($sql)->execute([$code])->fetchAll();
foreach ($data as $info) {
print_r($info);
}

php pdo function connect to DB and do query

I am trying to be as efficient with code as possible. Unfortunately, I can't seem to figure out a good way of doing this. I have tried using Sammitch's code which does look cleaner but unfortunately it doesn't seem to work.
I would like a way to stop having to use prepare, execute, every time and a function to me makes the most sense. Using Simmitch's suggestion, I removed the initial connection to database to stop unnecessary overheads but the code still does not work. Showing a "SQLSTATE[HY093]: Invalid parameter number: parameter was not defined" error.
My code at present (some parts omitted as not necessary):
/*Function to talk to database*/
function doQuery($myDB, $myQuery, $myValues)
{
try
{
$st = $myDB->prepare($myQuery);
$st->execute($myValues);
//echo $success;
}
catch (PDOException $e)
{
echo "Failed because: " . $e->getMessage();
}
}
$db = new PDO('mysql:host=localhost;dbname='dbanme';charset=utf8', 'dbuser', 'dbpass');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //Set error mode
$query = "INSERT INTO users(login,pass,email,county) VALUES(:username,:password,:email,:count)";
$values = array('username' => $_POST['username'],
'password' => $_POST['password1'],
'email' => $_POST['email'],
'county' => $_POST['county']
);
doQuery($db, $query, $values);
<?php
function doQuery($db, $query, $arguments) {
try {
//Prepare and execute an insert into DB
$st = $db->prepare($query);
$st->execute(array($values));
echo $success; // 4. use echo
// you should probably return something here...
} catch (PDOException $e) {
// 5. Fail ~descriptively~
echo "Failed because: " . $e->getMessage();
// you should probably return something here...
}
}
// 1. Don't create the database inside of the same function that does the queries,
// creation/destruction of the objects/connections will cause unnecessary overhead,
$myDb = new PDO('mysql:host=localhost;dbname=dbname;charset=utf8', 'dbuser', 'dbpassword');
$myDb->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //Set error mode
$myQuery = "INSERT INTO users(login,pass,email,county) VALUES(:username,:password,:email,:count)";
// 2. You can't define an array like that.
// 3. You do not need to add colons to the array indexes.
$myValues = array(
'username' => $_POST['username'],
'password' => $_POST['password1'],
'email' => $_POST['email'],
'county' => $_POST['county']
);
doquery($myDb, $myQuery, $myValues)
Don't forget to include " : " in your parameters array ?
/*Function to talk to database*/
function doQuery($myDB, $myQuery, $myValues)
{
try
{
$st = $myDB->prepare($myQuery);
$st->execute(array($myValues));
//echo $success;
}
catch (PDOException $e)
{
echo "Failed because: " . $e->getMessage();
}
}
$db = new PDO('mysql:host=localhost;dbname='dbanme';charset=utf8', 'dbuser', 'dbpass');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //Set error mode
$query = "INSERT INTO users(login,pass,email,county) VALUES(:username,:password,:email,:count)";
$values = array(':username' => $_POST['username'],
':password' => $_POST['password1'],
':email' => $_POST['email'],
':county' => $_POST['county']
);
doQuery($db, $query, $values);
I hope this worked!

Categories