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?
Related
i have the following function:
public function insertMomentToDB($uid, $type, $data)
{
$stmt = $this->conn->prepare("INSERT INTO moments_newsfeed(user_id, type, time, data) VALUES(?, ?, NOW(), ?)");
$stmt->bind_param("sss", $uid, $type , $data);
$result = $stmt->execute();
$stmt->close();
// check for successful store
if ($result)
{
return true;
}
else
{
return false;
}
}
where $data = json undecoded, i want to put it in json format inside the table
$result is always null so it returns false..
I need to know how to get the result of a select statement that is executed after an insert statement as one execute in PDO.
My PDO connection parameters are as follows:
$opt = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => true];
$conn = new PDO($dsn, $user, $pass, $opt);
I have the following helper function that i use for my PDO statement Execution:
function databaseExecute($SQL, $BIND_P, &$BIND_R) {
global $conn;
$stmt = $conn->prepare($SQL);
if ($stmt->execute($BIND_P)) {
if ($BIND_R !== false) {
//Type testing is important here
$tmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt->closeCursor();
if (!$tmp || count($tmp) == 0) {
return false;
}
$BIND_R = $tmp;
} else {
$stmt->closeCursor();
}
return true;
}
$stmt->closeCursor();
return false;
}
My function itself is:
/**
* Adds the current purchase object to the database table
* #return true if success
*/
public function pushToDB() {
global $tbl_purchases;
//We don't push purchaseID since that field is auto handled by the database
$sql = "INSERT INTO " . $tbl_purchases . " (ProductID, UID, TID, GenDate, KeyIDs, Total, Assigned) VALUES (?, ?, ?, ?, ?, ?, ?); SELECT LAST_INSERT_ID();";
$result = array();
if (databaseExecute($sql, array(
$this->getProductID(),
$this->getUID(),
$this->getTID(),
$this->getGenDate(),
$this->getKeyIDsJSON(),
$this->getTotal(),
$this->getAssigned(),
), $r)) {
var_dump($result);
$this->_setPurchaseID($result[0]);
return true;
}
trigger_error("Purchase::pushToDB - Could not push purchase to database", E_USER_ERROR);
return false;
}
But this throws a general error
Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error when i attempt to fetchAll
In this situation, how do i get the result of the SQL execution?
PS: Using Two executes is not acceptable here.
Using Two executes is not acceptable here.
This is but a delusion.
Use either second query or - better - a dedicated function PDO::LastInsertId(). But with your rather poorly designed function it could be a problem. So be it 2 queries.
So change your functions to
function databaseExecute($SQL, $BIND_P = array();) {
global $conn;
if (!$BIND_P)
{
return $conn->query($SQL);
}
$stmt = $conn->prepare($SQL);
$stmt->execute($BIND_P);
return $stmt;
}
and
public function pushToDB() {
global $tbl_purchases;
//We don't push purchaseID since that field is auto handled by the database
$sql = "INSERT INTO $tbl_purchases
(ProductID, UID, TID, GenDate, KeyIDs, Total, Assigned)
VALUES (?, ?, ?, ?, ?, ?, ?)";
databaseExecute($sql, array(
$this->getProductID(),
$this->getUID(),
$this->getTID(),
$this->getGenDate(),
$this->getKeyIDsJSON(),
$this->getTotal(),
$this->getAssigned(),
));
$id = databaseExecute("SELECT LAST_INSERT_ID()")->fetchColumn();
$this->_setPurchaseID($db);
return true;
}
}
You can alter your databaseExectute function to take an extra parameter of 'SecondResult' (for example), then change it to something like...
function databaseExecute($SQL, $BIND_P, &$BIND_R,$SecondResult) {
global $conn;
$stmt = $conn->prepare($SQL);
if ($stmt->execute($BIND_P)) {
if ($BIND_R !== false) {
//Type testing is important here
if ($SecondResult) $stmt->nextRowSet(); // this will ensure that the fetchAll will return the data from the 2nd query
$tmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt->closeCursor();
if (!$tmp || count($tmp) == 0) {
return false;
}
$BIND_R = $tmp;
} else {
$stmt->closeCursor();
}
return true;
}
$stmt->closeCursor();
return false;
}
I just typed this in to here directly, I haven't tested it, but it should work.
Also, I'm not saying that the other comments are wrong, and there might be a better way of doing this, but you CAN run two queries within the same 'statement'.
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'm trying to use prepared queries, but this code isn't working, it just stucks on the first use of prepare(). Commenting the fist if() does nothing, now it stucks on the second. No connection problems/no errors, just stuck.
If I do all of this using just mysqli_query() everything works great.
function addUser($id){
/*
if ($stmt = $this->mysqli->prepare("SELECT * FROM Users WHERE ID = ?")){
if (!($stmt->bind_param("s", $id))){
return false;
}
if ($stmt->execute()) {
if ($stmt->num_rows!=0){
return false;
}
}else{
return false;
}
}else{
return false;
}*/
if ($stmt = $this->mysqli->prepare("INSERT INTO Users VALUES (?, '')")) {
if (!$stmt->bind_param("s", $id)) {
return false;
}
if (!$stmt->execute()) {
return false;
}
return true;
}
return false;
}
and about debugging, if i change the code like this
function addUser($id){
echo "1";
if ($stmt = $this->mysqli->prepare("SELECT * FROM Users WHERE ID = ?")){
echo "2";
if (!($stmt->bind_param("s", $id))){
return false;
} ...
}else{
echo "3";
} ...
I'll see only "1" on the page.
start of the class:
class db{
private $mysqli;
function __construct($ip, $login, $password, $database){
$this->mysqli = new mysqli($ip, $login, $password, $database) or die("Problem with DB connection!");
$this->mysqli->set_charset("utf8");
}
You never execute() so nothing will happen, therefore no errors will raise.
Here is how I would write it:
function addUser($id){
if ($this->mysqli->connect_errno) {
die('Connect Error: ' . $this->mysqli->connect_errno);
}
if ($stmt = $this->mysqli->prepare("INSERT INTO Users VALUES (?, '')")) {
$stmt->bind_param("s", $id);//did you mean i for type int ?
$stmt->execute();//dont forget this!!
}else{
die('Connect Error: ' . $this->mysqli->connect_errno);
}
return ($stmt->rowCount() > 0)? true : false;
}
i got two methods.one method is to insert data and the other one is to get the id of the inserted data. i tried several test but it doesn't give any return value.is it possible to pass a return value from another method?
public function insertRegistrantInfo($fname, $lname) {
$query = $this->db->prepare("INSERT INTO `registrants_info` (`first_name`, `last_name`) VALUES (?,?)");
$query->bindValue(1, $fname);
$query->bindValue(2, $lname);
try {
$row = $query->execute();
//$log = $this->getSessionID($email);
return $this->getSessionID($email);
#mail function can be added here
}catch(PDOException $e) {
die($e->getMessage());
}
}
public function getSessionID($email) {
try {
//global $bcrypt;
$query = $this->db->prepare("SELECT `id` FROM `registrants_info` WHERE `email` = ?");
$query->bindValue(1, $email);
$query->execute();
$data1 = $query->fetch();
$id = $data1['id'];
//echo $id;
return $id;
} catch(PDOException $e) {
die($e->getMessage());
}
}
and the returning page is here:
if($data = $admin->insertRegistrantInfo($fname, $lname) == true) {
session_regenerate_id(true);
$_SESSION['id'] = $data;
//print_r($_SESSION);
header('location: registry.php');
exit();
}
Use the lastInsertID() method on your query object rather than a second query
public function insertRegistrantInfo($fname, $lname) {
$query = $this->db->prepare("INSERT INTO `registrants_info` (`first_name`, `last_name`) VALUES (?,?)");
$query->bindValue(1, $fname);
$query->bindValue(2, $lname);
try {
$row = $query->execute();
$insertId = $query->lastInsertId(); // <!-- Use this instead of a second query
#mail function can be added here
}catch(PDOException $e) {
die($e->getMessage());
}
}
Its also important to note that you are not inserting the 'email address' into your database, so there is no way for the query to find it by that field if you were to use another SELECT statement. You might want to complete your INSERT statement.