get lastInsertId using PDO - php

I am unable to get the lastInserId using PDO in php
$conn = new Db();
$query = "INSERT INTO orders SET
order_timestamp= :orderTimestamp ,
customer_id= :customerId";
$stmt = $conn->dbConnect()->prepare($query);
$stmt->bindParam(':orderTimestamp', date("Y-m-d H:i:s"), PDO::PARAM_STR);
$stmt->bindParam(':customerId', $_SESSION["customerId"], PDO::PARAM_INT);
$stmt->execute();
$orderId = $conn->lastInsertId();
return $orderId;
Below is the code used for DB Connection
public function dbConnect(){
try {
$conn = new PDO('mysql:host='.DBHOST.';dbname='.DBNAME, DBUSER, DBPASSWORD);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
return $conn;
}
I am getting an error as mentioned below.
Strict Standards: Only variables should be passed by reference in
H:\xampp\htdocs\php\tuf4\hunger\includes\classes\class.hunger.php on
line 31
Fatal error: Call to undefined method Db::lastInsertId() in
H:\xampp\htdocs\php\tuf4\hunger\includes\classes\class.hunger.php on
line 34

bindParam expects a variable, to be passed by reference. date("Y-m-d H:i:s") is clearly not a variable ;)
Try bindValue instead.
Using the correct function will stop the domino effect of errors, and allow you to get the lastInsertId you are seeking.
EDIT: On further review, you are trying to call lastInsertId on your Db wrapper class, not on the PDO object. Try:
$pdo = $conn->dbConnect();
$stmt = $pdo->prepare($query);
// ...
$orderId = $pdo->lastInsertId();

Related

php transaction error, i always get a rollback error [duplicate]

This question already has answers here:
PHP PDO - There is no active transaction
(2 answers)
Closed 2 years ago.
im trying to update 2 tables at once. from my research i have to use a transaction for this:
protected function myUpdateFunction(){
try{
$this->connect()->beginTransaction();
$itemID = filter_input(INPUT_POST, 'updateItemID');
$itemName = filter_input(INPUT_POST, 'updateItemName');
$itemDescription = filter_input(INPUT_POST, 'updateItemDescription');
$itemPrice = filter_input(INPUT_POST, 'updateItemPrice');
$itemStock = filter_input(INPUT_POST, 'updateItemStock');
$updateItemBtn = filter_input(INPUT_POST, 'updateItemBtn');
$sql = "UPDATE oopphp_items SET itemName = ?, itemDescription = ?, itemPrice = ?, itemStock = ? WHERE itemID = ?";
$stmt = $this->connect()->prepare($sql);
$stmt->bindParam(1, $itemName, PDO::PARAM_STR);
$stmt->bindParam(2, $itemDescription, PDO::PARAM_STR);
$stmt->bindParam(3, $itemPrice, PDO::PARAM_STR);
$stmt->bindParam(4, $itemStock, PDO::PARAM_INT);
$stmt->bindParam(5, $itemID, PDO::PARAM_INT);
$stmt->execute();
//wishlist
$itemID_fk = filter_input(INPUT_POST, 'updateItemID');
$itemName_fk = filter_input(INPUT_POST, 'updateItemName');
$itemDescription_fk = filter_input(INPUT_POST, 'updateItemDescription');
$itemPrice_fk = filter_input(INPUT_POST, 'updateItemPrice');
$sql = "UPDATE oopphp_wishlist SET itemName_fk = ?, itemDescription_fk = ?, itemPrice_fk = ? WHERE itemID_fk = ?";
$stmt = $this->connect()->prepare($sql);
$stmt->bindParam(1, $itemName_fk, PDO::PARAM_STR);
$stmt->bindParam(2, $itemDescription_fk, PDO::PARAM_STR);
$stmt->bindParam(3, $itemPrice_fk, PDO::PARAM_STR);
$stmt->bindParam(4, $itemID_fk, PDO::PARAM_INT);
$stmt->execute();
$this->connect()->commit();
}
catch(Exception $e){
echo $e->getMessage();
$this->connect()->rollBack();
}
}
i get the following error:
Fatal error: Uncaught PDOException: There is no active transaction
when i tried looking for answers they all said to put it inside a try-catch, which i already did. all examples i could find do it like this. as seen here: PHP PDO - There is no active transaction
i also found some people suggest adding these to the database file:
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute( PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, FALSE);
which also hasent done anything.
now if i just remove the code inside the catch() then the error goes away and i both my update queries work.
the only difference i could spot is that all examples dont have their database connection as a function.
so where i do:
$this->connect()->beginTransaction();
they do:
$pdo->beginTransaction();
and obviously same for commit() and rollBack(). though i cant imagine this being the problem. especially when it works perfectly if i remove the catch() content.
this is where i got the code from: https://thisinterestsme.com/php-pdo-transaction-example/
i seem to have the same code apart from the connect() vs $pdo.
my connect function:
protected function connect(){
try{
$dsn = 'mysql:host=' . $this->DB_HOST . ';dbname=' . $this->DB_NAME;
$pdo = new PDO($dsn, $this->DB_USER, $this->DB_PASS);
//setting default fetch mode
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
//setting errors for exceptions for try/catch
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute( PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
return $pdo;
}
catch(PDOException $error){
echo 'Connection error: ' . $error->getMessage();
}
finally{
//$pdo = null;
}
}
i fixed it with the help of the comment, and a final note at the end if someone sees this later:
this line i mentioned: $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, FALSE);
made it so my CRUD didnt work anymore. the other 2 setAttribute() didnt cause errors with anything at this moment.
When you call connect(), you get a different PDO object each time. Thus,
$this->connect()->beginTransaction(); // pdo object 1
$this->connect()->commit(); // pdo object 4
PDO object 4 has no transaction in progress! the Exception is normal.
Quick fix :
in you try block
$pdo = $this->connect();
$pdo->beginTransaction();
.... // replace all $this->connect() by $pdo
$pdo->commit();

Cannot execute prepared statement "Fatal error: Call to a member function prepare() on null" error

So I have this code
$lang=new language();
$default_language=$lang->getLanguage(0);
$currencies = new currency();
$currencies = $currencies->getCurrencies();
getCurrencies() and getLanguage() are in another file with classes.
public function getCurrencies() {
$curr=new record();
return $curr -> getRecords('currencyTable','currency_order',array("currency_id","currency_name"));
}
public function getLanguage($record) {
$lang=new record();
return $lang->getRecord('languageTable',$record,'lang_order','*');
}
And getRecords and getRecord are public functions it the record class
I keep on getting the error
Fatal error: Call to a member function prepare() on null
Referring to the query of the getRecords functions.
I dont know how to fix this. Does this has to do with the connection to the database?
Also, the weird part is that if I remove the
$lang=new language();
$default_language=$lang->getLanguage(0);
part, this error goes away. Any help? Is the error in the $default_language=$lang->getLanguage(0); line and this is why it is messing up the database connection, resulting to this error?
Thanks
EDIT
Here are the getRecord and getRecords
public function getRecords($table,$sorder,$field_names) {
$conn = db::open();
//- build string of field names
if($field_names!='*'){
$field_string="";
foreach ($field_names as $value) {
$field_string.=",".$value;
}
$field_string = substr($field_string,1);
}else{
$field_string='*';
}
//end up with field1, field2... or *
//soreder is a field, contains int like 1 2 3
//- run statement
$stmt = $conn->prepare("SELECT ".$field_string." FROM ".$table." ORDER BY ".$sorder." ASC");
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $results;
}
and
public function getRecord($table,$record,$sorder,$field_names) {
$conn = db::open();
if($field_names!='*'){
$field_string="";
foreach ($field_names as $value) {
$field_string.=",".$value;
}
$field_string = substr($field_string,1);
}else{
$field_string='*';
}
//same things for $field_string and $sorder
$stmt = $conn->prepare("SELECT ".$field_string." FROM ".$table." ORDER BY ".$sorder." LIMIT ? OFFSET ?");
$stmt->bindValue(1, 1 , PDO::PARAM_INT);
$stmt->bindValue(2, $record, PDO::PARAM_INT);
$stmt->execute();
$results = $stmt->fetch(PDO::FETCH_ASSOC);
return $results;
}
I fixed an error. In getRecord I had LIMIT 1 and I fixed it as above. I still get the same error about the getRecords line : $stmt = $conn->prepare("SELECT ".$field_string." FROM ".$table." ORDER BY ".$sorder." ASC");
Any thoughts?
Thanks
Your database connection failed. The error is not in your posted code. The error in your code is when the statement is being prepared.
Ex: $statement = $dbh->prepare("SELECT * FROM some_table"). I would recommend throwing an exception to see what's going wrong with your connection. You can do this by adding the options to your pdo initialization. array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
try{
$dbh = new PDO('mysql:host='.MYSQL_HOST.';dbname='.MYSQL_DB,
MYSQL_USERNAME,
MYSQL_PASSWORD,
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
}catch(Exception $e){
echo $e->getMessage();
}
Hope this helps

Call to a member function fetch() on boolean [duplicate]

This question already has answers here:
Why does this PDO statement silently fail?
(2 answers)
Closed 2 years ago.
I receive this error:
Fatal error: Call to a member function fetch() on boolean in
C:\xampp\htdocs\repo\generator\model\database.php on line 34
When I run this code:
class database
{
private $user = 'root';
private $pass = '';
public $pdo;
public function connect() {
try {
$this->pdo = new PDO('mysql:host=localhost; dbname=generatordatabase', $this->user, $this->pass);
echo 'Połączenie nawiązane!';
}
catch(PDOException $e) {
echo 'Połączenie nie mogło zostać utworzone: ' . $e->getMessage();
}
}
public function createTable() {
$q = $this->pdo -> query('SELECT * FROM article');
while($row = $q->fetch()) {
echo $row['id'].' ';
}
$q->closeCursor();
}
}
?>
As per the PHP manual for PDO::query
PDO::query() returns a PDOStatement object, or FALSE on failure.
It looks like your query is failing (on line 33) and thus returning a BOOLEAN (false), likely because at that point in execution, PDO has not connected to a database that contains a table called article. In the connect() method I see that it tries to connect to a db called 'generatordatabase'; ensure this connection is being made prior to calling createTable(), otherwise ensure that it contains a table called 'article'.
I would recommend adding some more code examples, for instance the code that calls this class/method before the error is triggered.
Some error handling will help you avoid issues like this:
$q = $this->pdo->query('SELECT * FROM article');
//error case
if(!$q)
{
die("Execute query error, because: ". print_r($this->pdo->errorInfo(),true) );
}
//success case
else{
//continue flow
}
I'm not sure wheatear this is exactly the error I struggled with, but my error was due to my $con variable, I used a single $con for 2 SQL statements, for example:
$con = new mysqli($host,$username,$password,$database);
$sql = "SELECT name FROM users WHERE email = '$email'";
$stm = $con->prepare($sql);
$stm->execute();
and
$sql1 = "INSERT INTO posts
VALUES('$email','$body')";
$stm1 = $con->prepare($sql1);
if ($stm1->execute()) {
I should have done:
$con = new mysqli($host,$username,$password,$database);
$sql = "SELECT name FROM users WHERE email = '$email'";
$stm = $con->prepare($sql);
$stm->execute();
and
$con1 = new mysqli($host,$username,$password,$database);
$sql1 = "INSERT INTO posts
VALUES('$email','$body')";
$stm1 = $con1->prepare($sql1);
$stm1->execute()

PHP/PDO function return value from database variable parameters

I am trying to write this basic function to get a value from a table.
<?php
function getvalue($value, $from, $id){
//Returns the value of a table
require('includes/connect.php');
$db = new PDO('mysql:host=localhost;dbname='.$database, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT :value AS value
FROM :from
WHERE id = :id
LIMIT 1";
$stmt = $db->prepare($sql);
$stmt->bindParam(':value', $value, PDO::PARAM_STR);
$stmt->bindParam(':from', $from, PDO::PARAM_STR);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
$data = $stmt->fetch();
$return = $data['value'];
return $return;
}//function
?>
It gives this Fatal error:
Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''project' WHERE id = '1'' at line 2' in /functions/getvalue.php:26 Stack trace: #0 /functions/getvalue.php(26): PDOStatement->execute() #1 /
test.php(24): getvalue('tarief', 'project', '1') #2 {main} thrown in /functions/getvalue.php on line 26
Although your idea of having such a function is excellent, the implementation is just terrible. Some essential drawbacks are:
you are connecting to database every time this function is called
this code is prone to SQL injection
yet it is awfully inflexible, letting you to run no query different from silly SELECT ... WHERE id. Eventually you will learn other queries and find this function unusable.
It should be a function that accepts an SQL query and array with parameters to bind:
<?php
//Returns the value of a query
function getvalue($sql, $params = array())
{
global $pdo;
$stmt = $db->prepare($sql);
$stmt->execute($params);
return $stmt->fetchColumn();
}
require('includes/connect.php');
$name = getValue("SELECT name FROM users WHERE id =?",array($_GET['id']))
simple, robust and usable.
While connection string better to be moved into includes/connect.php
$dsn = "mysql:host=localhost;dbname=$database;charset=utf8";
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
$pdo = new PDO($dsn, $username, $password, $opt);
Try this (be sure $value and $from variables values are escaped):
<?php
function getvalue($value, $from, $id){
//Returns the value of a table
require('includes/connect.php');
$db = new PDO('mysql:host=localhost;dbname='.$database, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT " . $value . " AS value
FROM " . $from . "
WHERE id = :id
LIMIT 1";
$stmt = $db->prepare($sql);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
$data = $stmt->fetch();
$return = $data['value'];
return $return;
}//function
?>

How to handle PDO exceptions [duplicate]

This question already has answers here:
Why does this PDO statement silently fail?
(2 answers)
Closed 7 years ago.
I'm trying to work with PDO class on php but I have some trouble to find the right way to handle errors, I've wrote this code:
<?php
// $connection alreay created on a class which works with similar UPDATE statements
// I've simply added here trim() and PDO::PARAM... data type
$id = 33;
$name = "Mario Bros.";
$url = "http://nintendo.com";
$country = "jp";
try {
$sql = "UPDATE table_users SET name = :name, url = :url, country = :country WHERE user_id = :user_id";
$statement = $connection->prepare ($sql);
$statement->bindParam (':user_id', trim($id), PDO::PARAM_INT);
$statement->bindParam (':name', trim($name), PDO::PARAM_STR);
$statement->bindParam (':url', trim($url), PDO::PARAM_STR);
$statement->bindParam (':country', trim($country), PDO::PARAM_STR, 2);
$status = $statement->execute ();
} catch (PDOException $e) {
print $e->getMessage ();
}
print $status; // it returns a null value, and no errors are reported
?>
this portion of code doesn't report errors, but it simply doesn't work, the var $status at the bottom, return a null value.
can someone help me to find where I'm wrong?
PDO won't throw exceptions unless you tell it to. Have you run:
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
on the PDO object?
You can add the attribute one time while you connect you mysql.
function connect($dsn, $user, $password){
try {
$dbh = new PDO($dsn, $user, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
exit;
}
}
Thanks

Categories