So I want to get and return last inserted id from query.
I am successfully get the last inserted id but I have a little problem when try to return it to index.php file
This is my method code :
public function InsertUserCard(UserCard $uc)
{
if(!$this->DuplicateUserCard($uc))
{
$stmt = $this->conn->prepare("INSERT INTO ".$this->table_name."
(user_id, card_id, barcode, barcode_format, created_at, updated_at)
VALUES(?, ?, ?, ?, ?, ?)");
if ($stmt == FALSE)
{
die($this->conn->error);
}
else
{
$user_id = NULL;
$card_id = NULL;
$barcode = NULL;
$barcode_format = NULL;
$created_at = NULL;
$updated_at = NULL;
$stmt->bind_param("iissss", $user_id, $card_id, $barcode, $barcode_format, $created_at, $updated_at);
$user_id = $uc->getUserId();
$card_id = $uc->getCardId();
$barcode = $uc->getBarcode();
$barcode_format = $uc->getBarcodeFormat();
$created_at = $uc->getCreatedAt();
$updated_at = $uc->getUpdatedAt();
$stmt->execute();
$result = $this->conn->insert_id; <-- This is how I get the last inserted id
$stmt->close();
}
// Check for successful insertion
if ($result)
{
// User card successfully inserted
return USER_CARD_INSERTED_SUCCESSFULLY;
}
else
{
// Failed to insert user card
return USER_CARD_INSERT_FAILED;
}
}
else
{
return USER_CARD_ALREADY_EXISTED;
}
}
and this is my index.php file
$app->post('/user/card/rev', 'authenticate', function() use ($app)
{
// check for required params
verifyRequiredParams(array('user_id', 'card_id', 'barcode', 'barcode_format', 'created_at', 'updated_at'));
global $user_id;
$response = array();
$timestamp = time();
$now = date("Y-m-d H:i:s", $timestamp);
$uc = new UserCard();
$uc->setUserId($user_id);
$uc->setCardId($app->request->post('card_id'));
$uc->setBarcode($app->request->post('barcode'));
$uc->setBarcodeFormat($app->request->post('barcode_format'));
$uc->setCreatedAt($app->request->post('created_at'));
$uc->setUpdatedAt($app->request->post('updated_at'));
// choose card from db by user
$UserCardDB = new UserCardDB(MySqlDb::getInstance()->connect());
$UserCard = $UserCardDB->InsertUserCard($uc);
if ($UserCard == USER_CARD_INSERTED_SUCCESSFULLY)
{
$response["error"] = false;
$response["message"] = "User Card added successfully";
$response["current_timestamp"] = $timestamp;
$response["current_date"] = $now;
$response["last_inserted_id"] = SHOULD_BE_HERE;
echoRespnse(201, $response);
}
});
as you see, I want to put the last inserted id on $response["last_inserted_id"], but I do not know how to do it.
any ideas ?
thanks:)
I think you have your statements backwards
$inserted_id = $this->conn->insert_id;
$result = $stmt->execute();
In prepared statements, execute is what runs your SQL. So you can't get the ID of what hasn't been inserted yet.
$result = $stmt->execute();
$inserted_id = $this->conn->insert_id;
You're also not storing the data anywhere usable ($inserted_id is a local variable to your function). Consider making a class variable like $this->inserted_id and making a function that would return that value.
Try this in you method:
public function InsertUserCard(UserCard $uc)
{
if(!$this->DuplicateUserCard($uc))
{
$stmt = $this->conn->prepare("INSERT INTO ".$this->table_name."
(user_id, card_id, barcode, barcode_format, created_at, updated_at)
VALUES(?, ?, ?, ?, ?, ?)");
if ($stmt == FALSE)
{
die($this->conn->error);
}
else
{
$user_id = NULL;
$card_id = NULL;
$barcode = NULL;
$barcode_format = NULL;
$created_at = NULL;
$updated_at = NULL;
$stmt->bind_param("iissss", $user_id, $card_id, $barcode, $barcode_format, $created_at, $updated_at);
$user_id = $uc->getUserId();
$card_id = $uc->getCardId();
$barcode = $uc->getBarcode();
$barcode_format = $uc->getBarcodeFormat();
$created_at = $uc->getCreatedAt();
$updated_at = $uc->getUpdatedAt();
}
// Check for successful insertion
if ($stmt->execute())
{
$result = $this->conn->insert_id;
$stmt->close();
return $result;
}
else
{
// Failed to insert user card
return USER_CARD_INSERT_FAILED;
}
}
else
{
return USER_CARD_ALREADY_EXISTED;
}
}
and in you index.php:
$app->post('/user/card/rev', 'authenticate', function() use ($app)
{
// check for required params
verifyRequiredParams(array('user_id', 'card_id', 'barcode', 'barcode_format', 'created_at', 'updated_at'));
global $user_id;
$response = array();
$timestamp = time();
$now = date("Y-m-d H:i:s", $timestamp);
$uc = new UserCard();
$uc->setUserId($user_id);
$uc->setCardId($app->request->post('card_id'));
$uc->setBarcode($app->request->post('barcode'));
$uc->setBarcodeFormat($app->request->post('barcode_format'));
$uc->setCreatedAt($app->request->post('created_at'));
$uc->setUpdatedAt($app->request->post('updated_at'));
// choose card from db by user
$UserCardDB = new UserCardDB(MySqlDb::getInstance()->connect());
$UserCard = $UserCardDB->InsertUserCard($uc);
if (($UserCard != "USER_CARD_INSERT_FAILED") and ($UserCard != "USER_CARD_ALREADY_EXISTED"))
{
$response["error"] = false;
$response["message"] = "User Card added successfully";
$response["current_timestamp"] = $timestamp;
$response["current_date"] = $now;
$response["last_inserted_id"] = $UserCard;
echoRespnse(201, $response);
}
});
The way I read that, your // Check for successful insertion section will never run because the function is terminated with return $result; before the conditional. Therefore, USER_CARD_INSERTED_SUCCESSFULLY is never returned.
In my functions, I usually return an array, for example:
$result = array( "status" => $status, "id" => $id );
return $result;
and, in the main:
$result = my_function();
$status = $result['status'];
$id = $result['id'];
I hope this help you!
In your method code instead of using $inserted_id use a $_SESSION variable $_SESSION['inserted_id']. Now you will be able to use this in your index.php
$response["last_inserted_id"] = $_SESSION['inserted_id '];
Related
I'm currently learning php and trying to write session data to my database without success.
I have a setup with Apache24, PHP 7 environment and Postgresql database.
When I instantiate sessionhandling class ($sess = new sessionhandling) in my other PHP file nothing is written to database. However, when I pass variable to and call the write function ($sess->write), data is written to the database.
(Hope this is not a duplicate of any other questions raised. Done a lot of searches on Stackoverflow and Google, but not found any answers that solve my challenge)
My session handler code is as follows:
<?php
Include(dirname(__DIR__).'\Userstories\db\Connection.php');
class sessionhandling extends Connecting implements SessionHandlerInterface {
public function __construct(){
// Set handler to overide SESSION
session_set_save_handler(
array(&$this, "open"),
array(&$this, "close"),
array(&$this, "read"),
array(&$this, "write"),
array(&$this, "destroy"),
array(&$this, "gc")
);
register_shutdown_function('session_write_close');
// Start the session
session_start();
session_write_close;
}
public function open($save_path, $id) {
if(self::get()->connect()) {
return true;
} else {
return false;
}
}
public function close() {
if(self::get()->connect()->pdo = Null) {
return true;
} else {
return false;
}
}
public function read($id) {
//$pdo = Connecting::get()->connect();
$ipdo = self::get()->connect();
$q_udata = "SELECT data FROM sessions WHERE id=:id";
$stmt=$ipdo->prepare($q_udata);
$stmt->bindvalue(':id', $id);
$stmt->execute();
if($stmt->execute()) {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$ipdo = NULL;
return $row['data'];
} else {
$ipdo = NULL;
return '';
}
}
public function write($id, $data){
$id = (string) $id;
$data = (string) $data;
$access = time();
$ipdo = self::get()->connect();
$c_id = "SELECT id FROM sessions WHERE id=:id";
$stmt=$ipdo->prepare($c_id);
$stmt->bindvalue(':id', $id);
$stmt->execute();
$idarray=$stmt->fetch(PDO::FETCH_ASSOC);
$row_id = $idarray['id'];
if(empty($row_id)) {
$sessionids = 'INSERT INTO sessions(id, data, access) VALUES(:id, :data, :access)';
$stmt = $ipdo->prepare($sessionids);
$stmt->bindvalue(':id', $id);
$stmt->bindvalue(':access', $access);
$stmt->bindvalue(':data', $data);
$stmt->execute();
session_write_close();
} else {
$rep_data = "UPDATE sessions SET data = :data, access = :access WHERE id = :id";
$stmt=$ipdo->prepare($rep_data);
$stmt->bindvalue(':id', $id);
$stmt->bindvalue(':access', $access);
$stmt->bindvalue(':data', $data);
$stmt->execute();
session_write_close();
}
if($stmt->execute()) {
$ipdo = NULL;
return true;
} else {
$ipdo = NULL;
return false;
}
}
public function destroy($id) {
$ipdo = self::get()->connect();
$del_data = "DELETE FROM sessions WHERE id =:id";
$stmt = $ipdo->prepare($del_data);
$stmt->bindvalue(':id', $id);
$stmt->execute();
if($stmt->execute()) {
$ipdo = NULL;
return true;
} else {
$ipdo = NULL;
return false;
}
}
public function gc($max) {
$old = time() - $max;
$ipdo = self::get()->connect();
$cleanup = "DELETE * FROM sessions WHERE access < :old";
$stmt = $ipdo->prepare($cleanup);
$stmt->bindvalue(':old', $old);
$stmt->execute();
if($stmt->execute()) {
$ipdo = NULL;
return true;
} else {
$ipdo = NULL;
return false;
}
}
}
?>
When I remove the 'implements SessionHandlerInterface' sessionhandling class and remove the parameters $save_path, $id from open function, I get the following error: "Warning: session_start(): Failed to read session data: user (path: ) in C:\Users\Public\Server\Apache24\htdocs\Userstories\sessionhandling.php on line 19"
Is it reuiqred to define the $save_path when using DB for session handling? If so, what should the $save_path be?
Any advise on how to get my session handler to write to DB is very much appreciated.
I made ut work by changing my read function to this and ensuring that a string is returned:
public function read($id) {
//$pdo = Connecting::get()->connect();
$ipdo = self::get()->connect();
$q_udata = "SELECT data FROM sessions WHERE id=:id";
$stmt=$ipdo->prepare($q_udata);
$stmt->bindvalue(':id', $id);
$stmt->execute();
if($stmt->execute()) {
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
$ipdo = NULL;
$data = $row['data'];
return (string) $data;
} else {
$ipdo = NULL;
return '';
}
}
I know this has been pointed out in other posts, but I thought that my $data = $row['data'] would return a string in the first place.
I'm hosting my files hostinger.in and is implementing REST architecture. When I was implementing the codes without REST, I was getting no error. But now it seems I can't access MySql Database. I narrow down possible errors which comes when I try registering a user and it seems the DB is inaccessible. Here are the codes:
public function sendOtp($mobile, $model, $brand, $device, $fingerprint, $hardware){
//Checking for User registration
if (!$this->isUserExists($mobile)) {
$otp = rand(100000, 999999);
$stmt = $this->con->prepare("INSERT INTO user_register(mobile, registered_mobile_model, registered_mobile_brand, registered_mobile_device, registered_mobile_fingerprint, registered_mobile_hardware, otp) values(?, ?, ?, ?, ?, ?, ?)");
$stmt->bind_param("sssssss", $mobile, $model, $brand, $device, $fingerprint, $hardware, $otp);
$result = $stmt->execute();
$stmt->close();
//If statment executed successfully
if ($result) {
//Returning 0, otp sent
return 0;
} else {
//Returning 1, failed to insert
return 1;
}
} else {
//user exists, update info and sent otp
$otp = rand(100000, 999999);
//Crating an statement
$stmt = $this->con->prepare("UPDATE user_register set otp = ?, registered_mobile_model = ?, registered_mobile_brand = ?, registered_mobile_device = ?, registered_mobile_fingerprint = ?, registered_mobile_hardware = ? WHERE mobile = ?");
//Binding the parameters
$stmt->bind_param("sssssss", $otp, $model, $brand, $device, $fingerprint, $hardware, $mobile);
//Executing the statement
$result = $stmt->execute();
//Closing the statement
$stmt->close();
//If statement executed successfully
if ($result) {
//Returning 0, user insert/update success, otp sent
return 0;
} else {
//Returning 1, failed to insert
return 1;
}
}
}
private function isUserExists($mobile) {
$stmt = $this->con->prepare("SELECT id from user_register WHERE mobile = ?");
$stmt->bind_param("s", $mobile);
$stmt->execute();
$stmt->store_result();
$num_rows = $stmt->num_rows;
$stmt->close();
return $num_rows > 0;
}
The index.php code to reroute the api calls:
$app->post('/sendotp', function () use ($app) {
//Verifying the required parameters
verifyRequiredParams(array('mobile', 'model', 'brand', 'device', 'fingerprint', 'hardware'));
//Creating a response array
$response = array();
//reading post parameters
$mobile = $app->request->post('mobile');
$model = $app->request->post('model');
$brand = $app->request->post('brand');
$device = $app->request->post('device');
$fingerprint = $app->request->post('fingerprint');
$hardware = $app->request->post('hardware');
//Creating a DbOperation object
$db = new DbOperation();
$res = $db->sendOtp($mobile, $model, $brand, $device, $fingerprint, $hardware);
//If the result returned is 0 means success
if ($res == 0) {
//Making the response error false
$response["error"] = false;
//Adding a success message
$response["message"] = "OTP Sent";
//Displaying response
echoResponse(201, $response);
//If the result returned is 1 means failure
} else if ($res == 1) {
$response["error"] = true;
$response["message"] = "Oops! An error occurred while registering";
echoResponse(200, $response);
}
});
I have this REST api code on backend:
public function createDay($user_id, $day, $startLocation, $startTime) {
$stmt = $this->conn->prepare("INSERT INTO days(day,startLocation,startTime,dayDate) VALUES(?,?,?,?)");
$stmt->bind_param("ssss", $day, $startLocation, $startTime, $dayDate);
$result = $stmt->execute();
$stmt->close();
if ($result) {
// task row created
// now assign the task to user
$new_day_id = $this->conn->insert_id;
$res = $this->createUserDay($user_id, $new_day_id, $dayDate);
if ($res) {
// task created successfully
return $new_day_id;
} else {
// task failed to create
return NULL;
}
} else {
// task failed to create
return NULL;
}
}
and function createDay:
public function createUserDay($user_id, $day_id, $dayDate) {
$stmt = $this->conn->prepare("INSERT INTO user_days(user_id, day_id, $dayDate) values(?, ?, ?)");
$stmt->bind_param("iis", $user_id, $day_id, $dayDate);
$result = $stmt->execute();
if (false === $result) {
die('execute() failed: ' . htmlspecialchars($stmt->error));
}
$stmt->close();
return $result;
}
}
this is dbhandler file, now i have a question -
I use
$new_day_id = $this->conn->insert_id;
to get ID of current data but also how I can get $dayDate to use into createUserDay function
So I need to get $dayDate and use it into createUserDay function, is there any way?
This is the update code
But I got the error : FATAL ERROR (Call to undefined method User::fetch_assoc())
this is my method code
public function getAllUsers(User $user)
{
$stmt = $this->conn->prepare("SELECT u.user_id, u.email, u.name, u.phone, u.picture, s.status
FROM ".$this->table_name." as u, status as s
WHERE u.status_id = s.status_id");
if($stmt == FALSE)
{
die($this->conn->error);
}
else
{
$stmt->execute();
$stmt->bind_result($user_id, $email, $name, $phone, $picture, $status);
while($stmt->fetch())
{
$user->setUserId($user_id);
$user->setEmail($email);
$user->setName($name);
$user->setPhone($phone);
$user->setPicture($picture);
$user->setStatus($status);
}
$stmt->close();
return $user;
}
}
and this is my code in index.php who called the object method.
$app->get('/users', 'authenticate', function()
{
global $user_id;
$response = array();
$user = new User();
// fetching all users
$userDB = new UserDb(MySqlDb::getInstance()->connect());
$result = $userDB->getAllUsers($user);
$response["error"] = false;
$response["users"] = array();
// looping through result and preparing users array
while ($user = $result->fetch_assoc())
{
$tmp = array();
$tmp["user_id"] = $user->getUserId();
$tmp["email"] = $user->getEmail();
$tmp["name"] = $user->getName();
$tmp["phone"] = $user->getPhone();
$tmp["picture"] = $user->getPicture();
$tmp["status"] = $user->getStatus();
array_push($response["users"], $tmp);
}
echoRespnse(200, $response);
});
please check my foreach, is it wrong ?
Thanks :)
getAllUsers returns an array of Users
so $result is an array of Users, not a database query result as you may expect.
then you call fetch_assoc() on $result, which is an array of users, and as it doesn't have this method, you get Call to undefined method User::fetch_assoc()
I'm inserting a new column collegename, branch, and gender but suddenly it's giving me this error...
Warning: mysqli_stmt::bind_param(): Number of variables doesn't match number of
parameters in prepared statement in C:\Users\Raj\PhpstormProjects\usercake\models
\class.newuser.php on line 148
What's that mean?
Actually I was inserting a new column into my database college, branch, year, and gender everything goes well but when I register myself it's shows the message your Registration is successfully submitted but suddenly it shows this error message as wells as?
Here is my source code:
<?php
class User
{
public $user_active = 0;
private $clean_email;
public $status = false;
private $clean_password;
private $username;
private $displayname;
public $sql_failure = false;
public $mail_failure = false;
public $email_taken = false;
public $username_taken = false;
public $displayname_taken = false;
public $activation_token = 0;
public $success = NULL;
function __construct($user,$display,$pass,$email)
{
//Used for display only
$this->displayname = $display;
//Sanitize
$this->clean_email = sanitize($email);
$this->clean_password = trim($pass);
$this->username = sanitize($user);
if(usernameExists($this->username))
{
$this->username_taken = true;
}
else if(displayNameExists($this->displayname))
{
$this->displayname_taken = true;
}
else if(emailExists($this->clean_email))
{
$this->email_taken = true;
}
else
{
//No problems have been found.
$this->status = true;
}
}
public function userCakeAddUser()
{
global $mysqli,$emailActivation,$websiteUrl,$db_table_prefix;
//Prevent this function being called if there were construction errors
if($this->status)
{
//Construct a secure hash for the plain text password
$secure_pass = generateHash($this->clean_password);
//Construct a unique activation token
$this->activation_token = generateActivationToken();
//Do we need to send out an activation email?
if($emailActivation == "true")
{
//User must activate their account first
$this->user_active = 0;
$mail = new userCakeMail();
//Build the activation message
$activation_message = lang("ACCOUNT_ACTIVATION_MESSAGE",array($websiteUrl,$this->activation_token));
//Define more if you want to build larger structures
$hooks = array(
"searchStrs" => array("#ACTIVATION-MESSAGE","#ACTIVATION-KEY","#USERNAME#"),
"subjectStrs" => array($activation_message,$this->activation_token,$this->displayname)
);
/* Build the template - Optional, you can just use the sendMail function
Instead to pass a message. */
if(!$mail->newTemplateMsg("new-registration.txt",$hooks))
{
$this->mail_failure = true;
}
else
{
//Send the mail. Specify users email here and subject.
//SendMail can have a third parementer for message if you do not wish to build a template.
if(!$mail->sendMail($this->clean_email,"New User"))
{
$this->mail_failure = true;
}
}
$this->success = lang("ACCOUNT_REGISTRATION_COMPLETE_TYPE2");
}
else
{
//Instant account activation
$this->user_active = 1;
$this->success = lang("ACCOUNT_REGISTRATION_COMPLETE_TYPE1");
}
if(!$this->mail_failure)
{
//Insert the user into the database providing no errors have been found.
$stmt = $mysqli->prepare("INSERT INTO ".$db_table_prefix."users (
user_name,
display_name,
password,
email,
college,
branch,
year,
gender,
activation_token,
last_activation_request,
lost_password_request,
active,
title,
sign_up_stamp,
last_sign_in_stamp
)
VALUES (
?,
?,
?,
?,
?,
?,
?,
?,
?,
'".time()."',
'0',
?,
'New Member',
'".time()."',
'0'
)");
$stmt->bind_param("sssssi", $this->username, $this->displayname, $secure_pass, $this->clean_email, $this->activation_token, $this->user_active);
$stmt->execute();
$inserted_id = $mysqli->insert_id;
$stmt->close();
//Insert default permission into matches table
$stmt = $mysqli->prepare("INSERT INTO ".$db_table_prefix."user_permission_matches (
user_id,
permission_id
)
VALUES (
?,
'1'
)");
$stmt->bind_param("s", $inserted_id);
$stmt->execute();
$stmt->close();
}
}
}
}
?>
You have 10 ? in your prepare statement but you passed 6 variables to it on $stmt->bind_param. You must pass exactly same variables as you have in statement. Your bind must be something like this:
$stmt->bind_param('isisississ', $int1, $str1, $int2, $str2, $int3, $str3, $str4, $int4, $str5, $str6);