This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can't get mysql_insert_id() to work
I want to print the last inserted id using lastInsertId() on this function:
private function adduser() {
if (!empty($this->error)) return false;
$params = array(
':user_level' => parent::getOption('default-level'),
':name' => $this->name,
':email' => $this->email,
':username' => $this->username,
':password' => parent::hashPassword($this->password)
);
parent::query("INSERT INTO `login_users` (`user_level`, `name`, `email`, `username`, `password`)
VALUES (:user_level, :name, :email, :username, :password);", $params);
$shortcodes = array(
'site_address' => SITE_PATH,
'full_name' => $this->name,
'username' => $this->username,
'email' => $this->email,
'password' => $this->password
);
$subj = parent::getOption('email-add-user-subj');
$msg = parent::getOption('email-add-user-msg');
$cid = parent::lastInsertId();
if(!parent::sendEmail($this->email, $subj, $msg, $shortcodes))
$this->error = _('ERROR. Mail not sent');
$this->result = "<div class='alert alert-success'>" . sprintf(_('Successfully added user <b>%s</b> to the database. Credentials sent to user.'), $cid) . "</div>";
}
I have added this:
$cid = parent::lastInsertId();
and then added $cid here:
$this->result = "<div class='alert alert-success'>" . sprintf(_('Successfully added user <b>%s</b> to the database. Credentials sent to user.'), $cid) . "</div>";
But I keep getting:
Fatal error: Call to undefined method Generic::lastInsertId() in
The database connection looks like this:
public function dbConn() {
include(dirname(__FILE__) . '/config.php');
try {
self::$dbh = new PDO("mysql:host={$host};dbname={$dbName}", $dbUser, $dbPass);
self::$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
} catch (PDOException $e) {
return '<div class="alert alert-error">'._('Database error: '). $e->getMessage() . '</div>';
}
}
Any ideas how I should properly add lastInsertId() ?
Replace
$cid = parent::lastInsertId();
with
self::$dbh->lastInsertId();
... as (it looks like) your connection object is stored in the dbh field of this anonymous class we're talking about.
LastInsertID is a method of PDO class.
You are calling it on the Generic class, that has no method LastInsertID();
Related
I want to do a transaction with php and my sql with PDO, the thing is that when i use the commit() function, the code returns a "FALSE" echo, but insert the data anyway. Maybe im doing something wrong, my code is this:
In the Connection class
protected function getConexion()
{
try
{
$params = array(PDO::ATTR_PERSISTENT=>true,PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8");
$this->conexion = new PDO($this->motor.":host=".self::$servidor.";dbname=".$this->db_name,self::$usuario,self::$password,$params);
return $this->conexion;
}
catch (PDOException $ex)
{
echo "Error en la conexión : " . $ex->getMessage();
}
}
and into my register function
if($miembro == "S")
{
try
{
$this->getConexion()->beginTransaction();
$sqlInsertUsuario = "INSERT INTO Usuario (apodo, password, correo, nombre, apellido, "
. "fchNacimiento, sexo, fchCreacion, ultimaSesion, ip, llave, activo, "
. "imgPerfil, nivel)"
. " VALUES (:apodo, :password, :correo, :nombre, :apellido, "
. ":fchNacimiento, :sexo, NOW(), NOW(), 'Ip aqui', :llave, '1', "
. "'imagen aqui', 'I')";
$sqlInsertCandidato = "INSERT INTO Candidato (correo) VALUES (:correo)";
$sentencia = $this->getConexion()->prepare($sqlInsertUsuario);
$sentencia->execute(array(':apodo' => $apodo, ':password' => $clave, ':correo' => $correo,
':nombre' => $nombre, 'apellido' => $apellido, 'fchNacimiento' => date($fchNacimiento),
':sexo' => $sexo, ':llave' => $llave));
$sentencia = $this->getConexion()->prepare($sqlInsertCandidato);
$sentencia->execute(array(':correo' => $correo));
$this->getConexion()->commit();
echo 'TRUE';
}
catch (Exception $ex)
{
$this->getConexion()->rollBack();
echo 'FALSE';
}
}
the problem is that returns "FALSE" but the data is inserted in the table anyway.
I found the problem, the thing is that I was calling the connection too many times in this method: $this->getConexion()->beginTransaction();
so the solution was to create a variable "$pdo" that saves the connection and later will use it for all the transaction.
$pdo = $this->getConexion();
$pdo->beginTransaction();
instead of this:
$sentencia = $this->getConexion()->prepare($sqlInsertUsuario);
$sentencia = $this->getConexion()->prepare($sqlInsertCandidato);
$this->getConexion()->commit();
use this:
$sentencia = $pdo->prepare($sqlInsertUsuario);
$sentencia = $pdo->prepare($sqlInsertCandidato);
$pdo->commit();
Here is a part of the code I am using to update the database.
It works, but I would like to redirect the user to another page if the database update is a success.
How can I do that ?
I know the header('Location: ../../');, but where to use it ?
$statement = $dbconnect->prepare("
UPDATE members
SET name = :fname, lastname = :lname, phone = :phone
WHERE member_id = :memberid
");
$dbconnect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$statement->execute(
array(
':fname' => "$fname",
':lname' => "$lname",
':phone' => "$phone",
':memberid' => "$memberid"
)
);
} catch(PDOException $e) {
die("ERROR: Could not connect. " . $e->getMessage());
}
Even tried the following, but no redirection
$statement->execute(array(':fname' => "$fname", ':lname' => "$lname", ':phone' => "$phone",':memberid' => "$memberid"));
if ($statement) {
header('Location: http://sitename.com');
} else {
echo 'It failed!';
}
You need to check the result from the PDOStatement::execute execution and use the correct binding when you execute a prepared statement with an array of insert values (named parameters). Note, that the result from the successful PDO::prepare call is a PDOStatement object, not a boolean value.
The folloling script, based on your code, is a possible solution to your problem:
<?php
try {
$dbconnect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$statement = $dbconnect->prepare("
UPDATE members
SET name = :fname, lastname = :lname, phone = :phone
WHERE member_id = :memberid
");
if ($statement === false) {
die("ERROR: Could not prepare statement.");
}
$result = $statement->execute(
array(
':fname' => $fname,
':lname' => $lname,
':phone' => $phone,
':memberid' => $memberid
)
);
if ($result) {
header('Location: http://sitename.com');
exit;
}
} catch(PDOException $e) {
die("ERROR: Could not connect. " . $e->getMessage());
}
?>
If you want to assume that your update was successful as long as you did not encounter any PDO errors (I assume that updates without errors are successful) you can write this:
$statement = $dbconnect->prepare("UPDATE members SET name = :fname, lastname = :lname, phone = :phone WHERE member_id = :memberid");
$dbconnect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$statement->execute(array(':fname' => "$fname", ':lname' => "$lname", ':phone' => "$phone",':memberid' => "$memberid"));
// if there were no errors redirect now
header('Location: ../../');
} catch(PDOException $e){
die("ERROR: Could not connect. " . $e->getMessage());
}
On another note outside of dev you should find a different way to handle the error: this is almost the same as not having a try/catch.
I have a table like so.
CREATE TABLE `GBPAUD` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`currency_pair` varchar(11) NOT NULL DEFAULT '',
`date` datetime NOT NULL,
`sell` float NOT NULL,
`buy` float NOT NULL,
`spread` float NOT NULL,
PRIMARY KEY (`id`)
)
I have written a script that opens CSV files, itterates the rows and inserts them into the table.
After the script has run and i look in the database the table appears like this.
The code that inserts the data looks like so.
private function insert($currencyPair, $date, $buy, $sell, $spread){
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$result_set = $this->pdo->prepare("INSERT INTO ".str_replace('_', '', $this->instrument)." (currency_pair, date, sell, buy, spread) VALUES (:currency_pair, :date, :sell, :buy, :spread)");
$result = $result_set->execute(array(':currency_pair' => $currencyPair, ':date' => $date, ':buy' => (float)$buy, ':sell' => (float)$sell, 'spread' => (float)$spread));
}
I print out the values just before the exacute stament and the values are correct.
Array
(
[:currency_pair] => GBP/AUD
[:date] => 2007-11-01 14:06:04.000
[:buy] => 2.273400
[:sell] => 2.272500
[spread] => 0
)
Anyone have any idea why its not inserting my data?
EDIT:
DB connection code
define("DSN", "mysql:dbname=rates_test;host=localhost;port=3306");
define("USER", "blah");
define("PASS", "blah");
$pdo = new PDO(DSN, USER, PASS);
EDIT 2
I have taken the insert out of the function and added to the while loop im doing so you can see whats happening.
while( false !== ( $data = fgetcsv($file) ) ) {
if(array(null) !== $data){ //skip blank lines
$currencyPair = $data[$column['columns']['instrument']];
$date = $data[$column['columns']['date']];
$sell = $data[$column['columns']['sell']];
$buy = $data[$column['columns']['buy']];
$spread = (float)$buy - (float)$sell;
echo "value => " . $currencyPair . "\r\n";
echo "value => " . $date . "\r\n";
echo "value => " . $sell . "\r\n";
echo "value => " . $buy . "\r\n";
echo "value => " . $spread . "\r\n";
echo var_dump(array(':currency_pair' => $currencyPair, ':date' => $date, ':buy' => (float)$buy, ':sell' => (float)$sell, ':spread' => (float)$spread));
$result_set = $this->pdo->prepare("INSERT INTO ".str_replace('_', '', $this->instrument)." (currency_pair, date, sell, buy, spread) VALUES (:currency_pair, :date, :sell, :buy, :spread)");
$result = $result_set->execute(array(':currency_pair' => $currencyPair, ':date' => $date, ':buy' => (float)$buy, ':sell' => (float)$sell, ':spread' => (float)$spread));
}
}
and here is the result
value => GBP/AUD
value => 2007-10-28 21:21:48.000
value => 2.229000
value => 2.229900
value => 0
array(5) {
[":currency_pair"]=> string(15) "GBP/AUD"
[":date"]=> string(47) "2007-10-28 21:21:48.000"
[":buy"]=> float(0)
[":sell"]=> float(0)
[":spread"]=> float(0)
}
Edit 3:
I solved it, but its a bit hacky. Also i have no control over over these CSV's so any invisible characters can be in it. Can anyone please confirm if this is enough to handle any invisible characters there may be? ( i have not put this into a function yet, but i am doing the same for ever variable im inserting)
$buy = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $buy);
$buy = (strpos($buy, ':') && strpos($buy, '-')) ? array_shift(explode('.', $buy)) : $buy;
I do not like what i am doing with the date, but i cannot think of any other ways (i cannot parse a legitamate date straight from the CSV because of the invisable characters) even without the invisible characters removed i cannot parse a date because some feilds have more than 6 micro seconds (PHP can only handel 6)
I just wrapped a bit of code around your posted code and it works fine. I did not even change the code for the spread to :spread suggestion.
I did however add a try/catch block as I see you set the mode to throw Exceptions, but the catch block was never activated.
<?php
class tst
{
private $pdo;
private $instrument = 'gbp_aud';
public function __construct()
{
/*** mysql hostname ***/
$hostname = 'localhost';
/*** mysql username ***/
$username = 'test';
/*** mysql password ***/
$password = 'test';
/*** database name ***/
$dbname = 'test';
try {
$this->pdo = new PDO("mysql:host=$hostname;dbname=$dbname;charset=UTF8", $username, $password);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
$this->pdo->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND,'SET NAMES UTF8');
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
exit;
}
}
private function insert($currencyPair, $date, $buy, $sell, $spread){
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$result_set = $this->pdo->prepare("INSERT INTO ".str_replace('_', '', $this->instrument)." (currency_pair, date, sell, buy, spread) VALUES (:currency_pair, :date, :sell, :buy, :spread)");
$result = $result_set->execute(array(':currency_pair' => $currencyPair, ':date' => $date, ':buy' => (float)$buy, ':sell' => (float)$sell, 'spread' => (float)$spread));
}
catch(PDOException $e) {
print_r($this->pdo->errorInfo());
exit;
}
}
public function doit($currencyPair, $date, $buy, $sell, $spread){
$this->insert($currencyPair, $date, $buy, $sell, $spread);
}
}
$test = new tst();
$currencyPair = 'GBP/AUD';
$date = '2007-11-01 14:06:04.000';
$buy = 2.273400;
$sell = 2.272500;
$spread = 0;
$test->doit($currencyPair, $date, $buy, $sell, $spread);
$currencyPair = 'GBP/AUD';
$date = '2007-11-02 13:06:04.000';
$buy = 2.276600;
$sell = 2.278800;
$spread = 0.4;
$test->doit($currencyPair, $date, $buy, $sell, $spread);
Results:
I just read your last question, and I have to assume that you still have some odd characters in your data feed to this process.
Do a var_dump() of the array that you feed to the ->execute() statement, that will likely show more than a simple print_r()
UPDATE
The issue is that the older files are encoded in UNICODE and the new files are simple ASCII single byte encoded.
I converted the Older files offline so to speak back to ASCII and this code loaded an old and new file quite happily
The only remaining complication if that the older files dont have column names on row 1 and the field order is a little different, but thats just a FLOC. See the code below.
<?php
class tst
{
private $pdo;
private $instrument = 'gbp_aud';
public function __construct()
{
/*** mysql hostname ***/
$hostname = 'localhost';
/*** mysql username ***/
$username = 'test';
/*** mysql password ***/
$password = 'test';
/*** database name ***/
$dbname = 'test';
try {
$this->pdo = new PDO("mysql:host=$hostname;dbname=$dbname;charset=UTF8", $username, $password);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
$this->pdo->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND,'SET NAMES UTF8');
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
exit;
}
}
private function insert($currencyPair, $date, $buy, $sell, $spread){
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$result_set = $this->pdo->prepare("INSERT INTO ".str_replace('_', '', $this->instrument)." (currency_pair, date, sell, buy, spread) VALUES (:currency_pair, :date, :sell, :buy, :spread)");
$result = $result_set->execute(array(':currency_pair' => $currencyPair, ':date' => $date, ':buy' => (float)$buy, ':sell' => (float)$sell, 'spread' => (float)$spread));
}
catch(PDOException $e) {
print_r($this->pdo->errorInfo());
exit;
}
}
public function doit($currencyPair, $date, $buy, $sell, $spread){
$this->insert($currencyPair, $date, $buy, $sell, $spread);
}
}
$test = new tst();
// One old and one new format file
$files = array('GBP_AUD_Week1.csv', 'GBP_AUD_Week5.csv');
foreach ($files as $file) {
$old_format = true;
if (($handle = fopen($file, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
// test old or new file layout
if ( $data[0] == 'lTid' ) {
// New file layout
$old_format = false;
// Skip the title row
continue;
}
if ( $old_format ) {
$test->doit($data[1], $data[2], $data[3], $data[4], $data[4]-$data[3]);
} else {
$test->doit($data[2], $data[3], $data[4], $data[5], $data[5]-$data[4]);
}
}
fclose($handle);
}
}
I have a class formhandller like this
<?php
include "config.php";
class formhandller {
var $dbinstance;
var $lastinsertedid;//The id from the basic information tabel
function __construct(){
$this->connectDb();
}
function pdoMultiInsert($tableName, $data, $pdoObject){
//Will contain SQL snippets.
$rowsSQL = array();
//Will contain the values that we need to bind.
$toBind = array();
//Get a list of column names to use in the SQL statement.
$columnNames = array_keys($data[0]);
//Loop through our $data array.
foreach($data as $arrayIndex => $row){
$params = array();
foreach($row as $columnName => $columnValue){
$param = ":" . $columnName . $arrayIndex;
$params[] = $param;
$toBind[$param] = $columnValue;
}
$rowsSQL[] = "(" . implode(", ", $params) . ")";
}
//Construct our SQL statement
$sql = "INSERT INTO `$tableName` (" . implode(", ", $columnNames) . ") VALUES " . implode(", ", $rowsSQL);
//Prepare our PDO statement.
$pdoStatement = $pdoObject->prepare($sql);
//Bind our values.
foreach($toBind as $param => $val){
$pdoStatement->bindValue($param, $val);
}
//Execute our statement (i.e. insert the data).
try {
return $pdoStatement->execute();
} catch(PDOException $e) {
var_dump($e->getMessage());
//show error
error_log($query." :".$e->getMessage(). "\n", 3, getcwd() . "/var/tmp/sql_error.log");
exit;
}
}
private function connectDb(){
try {
//create PDO connection
$this->dbinstance = new PDO("mysql:host=".DBHOST.";dbname=".DBNAME, DBUSER, DBPASS);
$this->dbinstance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
//show error
error_log($query." :".$e->getMessage(). "\n", 3, getcwd() . "/var/tmp/sql_error.log");
exit;
}
}
public function postBasicinformation(){
//Add the variables coming from the form .
$stmt = $this->dbinstance->prepare('INSERT INTO basic_information (company,name,designation,email,direct_line,mobile) VALUES (:company, :name, :designation, :email, :directline, :mobile)');
$stmt->execute(array(
':company' => $_POST['company'],
':name' => $_POST['name'],
':designation' => $_POST['designation'],
':email' => $_POST['email'],
':directline' => $_POST['directline'],
':mobile' => $_POST['mobile'],
));
$this->lastinsertedid = $this->dbinstance->lastInsertId('id');
//echo $this->lastinsertedid;
//$this->dbinstance=null;
}
public function postProjectawards(){
//An example of adding to our "rows" array on the fly.
for($i=0;$i<sizeof($_POST['nominee_company']);$i++){
$rowsToInsert[] = array(
'biid' => $this->lastinsertedid,
'award_type' => 'pa',
'category' => $_POST['nominee_category'][$i],
'company' => $_POST['nominee_company'][$i],
'name' => $_POST['nominee_name'][$i],
'designation' => $_POST['nominee_designation'][$i],
'award_title' => $_POST['nominee_title'][$i],
'contact' => $_POST['nominee_contact'][$i],
'email' => $_POST['nominee_email'][$i],
'remark' => $_POST['remarks'][$i]
);
}
//var_dump($rowsToInsert);
//Call our custom function.
$y =$this->pdoMultiInsert('nominee', $rowsToInsert, $this->dbinstance);
//$this->dbinstance=null;
}
}
Now my redirect page is like this
<?php
include "controller/formhandller.php";
$x = new formhandller();
if(isset($_POST['steps'])){
if($_POST['steps']==1){
$x->postBasicinformation();
$url = "nominee.php";
header('Location: '.$url);
die();
}
if($_POST['steps']==2){
$x->postProjectawards();
$url = "nominee2.php";
header('Location: '.$url);
die();
}
}
else {
header('Location: '.'index.php');
die();
}
When I am saving the first step that is using postBasicinformation() this function .
It saves in a table called basic_information and gets the id of the inserted row and initialize it to the variable
$lastinsertedid
I want to use this variable in all the next steps to store in other tables.
But right now I am getting NULL
any Idea
Thanks.
I think you are getting confused about the life cycle of a php script.
Anything you do in xxx.php is lost once that script finishes. All objects instantiated during the execution of xxx.php with be lost forever once it finishes.
If you want to preserve some information created in xxx.php for use in yyy.php you have to save it somewhere, either a file or a database or the SESSION or possibly a caching system.
I think this is where you are getting confused. So as you said in a comment if you want to use this lastinsertid in another script the most obvious place to save it between scripts is the $_SESSION array
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!