I'm trying to convert a code I write to use the php function mysqli_stmt_bind_param() instead of replacing tag in prewritten statement which I believe is not a good pratice.
So here one of the function I have today:
$idTag1="###";
$requestReplaceArray = array("%PRODUCT_ID%","%PLATFORM_ID%","%STATUS_ID%","%DATE%","%COMMENT%",$idTag1);
$updateRequest="UPDATE REQUEST
SET
id_product = %PRODUCT_ID%,
id_platform = %PLATFORM_ID%,
id_status = %STATUS_ID%,
last_modifier = '".$_SERVER['PHP_AUTH_USER']."',
last_modification_date='%DATE%',
last_comment = '%COMMENT%'
WHERE id =".$idTag1;
function updateRequest($id, $productID, $platformID, $statusID, $date, $comment){
global $requestReplaceArray, $updateRequest;
escapeArguments($id, $productID, $platformID, $statusID, $date,$comment);
/*if number value is empty replace by 'null'*/
$productID=replaceEmptyValueByNull($productID);
$platformID=replaceEmptyValueByNull($platformID);
$statusID=replaceEmptyValueByNull($statusID);
$dbConnection = getDbConnection();
$replacement = array($productID, $platformID, $statusID,$date ,$comment, $id);
$updateRequest = str_replace($requestReplaceArray, $replacement, $updateRequest);
if(! $result = mysqli_query( $dbConnection, $updateRequest ) ) {
mysqli_free_result($result);
$dbConnection->close();
return "Error MyU02, can't update the request #".$id;
}else{
mysqli_free_result($result);
$dbConnection->close();
return $id;
}
}
This code isn't perfect but it works except when a $date is NULL.
My objectives is to now use that synthax :
$requestReplaceString = "iiissi";
$updateRequest="UPDATE REQUEST
SET
id_product = ?,
id_platform = ?,
id_status = ?,
last_modifier = '".$_SERVER['PHP_AUTH_USER']."',
last_modification_date=?,
last_comment = ?
WHERE id =?";
function updateRequest($id, $productID, $platformID, $statusID, $date, $comment){
global $requestReplaceString, $updateRequest;
$dbConnection = getDbConnection();
$stmt = mysqli_prepare( $dbConnection, $updateRequest);
mysqli_stmt_bind_param($stmt, $requestReplaceString, $productID, $platformID, $statusID,$date ,$comment, $id);
if(mysqli_stmt_execute($stmt) ) {
mysqli_stmt_close($stmt);
$dbConnection->close();
return $id;
}else{
mysqli_stmt_close($stmt);
$dbConnection->close();
return "Error MyU02, can't update the request #".$id;
}
}
My main issue here is to set some value to null because trying to bind a php NULL is not working at all. So my question is how can I bind NULL with mysqli if it's possible ?
Edit: it does work and my mistake comes from my bad code, the code is now corrected.
Just bind it. It works perfectly. Any null value will be sent to server as mysql's NULL.
Also note that there is a fatal issue with your code: you are connecting to database for the every query. Which will just kill your server.
Related
I am creating message delete script in PHP MYSQLI. I have added zero value to update column. my script is working but I want to add zero value with bind parameters.
Here is my source code
<?php
require_once "config.php";
if (isset($_GET['to_id'])) {
$id = $_GET['to_id'];
$session_id = $_SESSION['userid'];
}
$stmt = $con->prepare("UPDATE pm SET from_delete = '0' WHERE id = ? AND from_id = ?");
$stmt->bind_param("ss", $id, $session_id);
if ($stmt->execute()) {
echo"deleted successfully";
} else {
echo "Failed to delete<br/>";
}
?>
Just add another placeholder ? and bind value to it:
$stmt = $con->prepare("UPDATE pm SET from_delete = ? WHERE id = ? AND from_id = ?");
$zero = '0';
$stmt->bind_param("sss", $zero, $id, $session_id);
i want to insert into a table depending on the id of the session:
here the code in class.php:
public function activate($activation, $id,$change,$userID){
$stm1= $this->conn->prepare("INSERT INTO `log` (`date`,`change`) VALUES(CURRENT_TIMESTAMP(),'$change') WHERE `user_id` =$userID");
($stm1->execute());
$stmt = $this->conn->prepare("UPDATE `segments` SET `activation` = '$activation' WHERE `id` = '$id'")
or die($this->conn->error);
if ($stmt->execute()) {
$stmt->close();
$this->conn->close();
return TRUE;
}
}
at the top of the page i have this:
require './config.php';session_start();$userID = $_SESSION['user_id'];
and in action.php where the action go i have this:
$conn = new db_class();
$conn->activate($activation, $id,$change,$userID);
echo "Updated successfully.";
exit;
the first query insert into log is not working \ please help
This should be a comment but I don't have the rep yet...
Primarily, you don't do that type of insert with a WHERE clause. The insert will fail.
As an aside, that insert is open to sql injection. Bind your your parameters. Also, you should add error handling. If you had that, you would see the insert fails. Quick example (1 way...there are other ways...and I assumed $change is a string and $userId is an int...)
$sql = 'INSERT INTO log
SET `date` = CURRENT_TIMESTAMP(),
change = :change,
user_id = :user_id;';
$stmt = $this->conn->prepare( $sql );
$stmt->bindParam( ':change', $change, PDO::PARAM_STR );
$stmt->bindParam( ':user_id', $userID, PDO::PARAM_INT );
$result = $stmt->execute();
if (!$result) {
// failure -> get and handle the error
$error_array = $stmt->errorInfo();
} else {
// do something
}
The docs can help > pdo::execute, pdo::errorinfo
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'.
is this piece of code correct syntax wise ?
I need to update some fields in a certain row in my database which i can access using email ... so is this right ?
public function storeData($emaill, $servicee, $ratee, $rated_clientss) {
$email = "samy#gmail.com";
$service = "lksdjfsdkljf";
$rate = "good";
$rated_clients = "20";
$stmt = $this->conn->prepare ( "UPDATE users SET service='$service' and SET rate='$rate' and SET rated_clients='$rated_clients' WHERE email='$email'" );
var_dump($stmt->execute ());
if ($stmt->execute ()) {
$data = $stmt->get_result ()->fetch_assoc ();
$stmt->close ();
return $data;
} else {
return NULL;
}
}
Prepared statments to not directly accept user input, instead, you need to pass them as a placeholder: ?, and then use bind_param() to fill in the type and the variable.
Observe:
$stmt = $this->conn->prepare ( "UPDATE users SET service=? and SET rate=? and SET rated_clients=? WHERE email=?" );
$stmt->bind_param('ssss', $service, $rate, $rated_clients, $email);
Now you can correctly ->execute the $stmt.
I insert data into a table called 'roster'. The first column (id_roster) is an id using mysql auto-increment.
I run a SELECT to find the id_roster
I use this id_roster to insert it into a table 'roster_par_membre' along with other data
if ($insert_stmt = $mysqli->prepare("INSERT INTO `roster`(`nom_roster`, `description_roster`, `id_organisation`, `created_by`, `creation_date`,`modified_by`) VALUES (?, ?, ?, ?, ?, ?)")) {
$insert_stmt->bind_param('ssiisi', $roster_name, $description_roster, $organisation_id, $user_id, $creation_date, $user_id);
if (!$insert_stmt->execute()) {
$reponse = 'Sorry, a database error occurred; please try later';
} else {
// if INSERT OK -> create a new line in roster_membre table
//1. get the roster_id
$sql = "SELECT r.id_roster
FROM roster r
WHERE r.nom_roster = ?
LIMIT 1";
$stmt = $mysqli->prepare($sql);
if ($stmt) {
$stmt->bind_param('s', $roster_name);
$stmt->execute(); // Execute the prepared query.
$stmt->store_result();
$stmt->bind_result($id_roster);
$stmt->fetch();
$level = 1;
//2. create a line with the roster_id and insert the membre as level 1
$insert_stmt = $mysqli->prepare("INSERT INTO `roster_par_membre`(`id_membre`, `id_roster`, `level`, `modified_by`) VALUES (?,?,?,?)");
$insert_stmt->bind_param('iiii', $user_id, $id_roster, $level, $user_id);
$insert_stmt->execute();
$reponse = 'success';
}
So far the code is working but it is not very nice.
Is there a way when we create a new line in a table to directly return a value (id with auto-increment) to be used in a sql query (to insert data into a second table)? or maybe to merge the two query (the two INSERT) in one statment?
short edit: it is an AJAX $response the return value (JSON)
Ok,solution:
//1. get the roster_id
$sql = "SELECT r.id_roster
FROM roster r
WHERE r.nom_roster = ?
LIMIT 1";
$stmt = $mysqli->prepare($sql);
if ($stmt) {
$stmt->bind_param('s', $roster_name);
$stmt->execute(); // Execute the prepared query.
$stmt->store_result();
$stmt->bind_result($id_roster);
$stmt->fetch();
Just need to replace all this part by
$id_roster = $mysqli->insert_id;
nice and easy. THANKS to albanx
these are the functions I used for query on projects that I do not want to use any framework (just php):
/**
*
* Executes query methods
* #param string $query the query string
* #param array $vals array of values
* #param bool $show show the query
* #return int/array/false
*/
function q($query, $vals=array(), $show_query=false)
{
$conn = new mysqli(...)
$offset = 0;
foreach ($vals as $v)
{
$cv = $conn->real_escape_string($v);//escape the value for avoiding sql injection
$fv = ($v===NULL) ? 'NULL':"'".$cv."'"; //if value is null then insert NULL in db
$qpos = strpos($query, '?', $offset);//replace the ? with the valeue
$query = substr($query, 0, $qpos).$fv.substr($query, $qpos+1);
$offset = $qpos+strlen($cv)+1;
}
$result = $conn->query($query);
if($show || $result===false) echo $query."<br>";
$rows = array();
if($result===true)
{
return $conn->affected_rows;
}
else if($result===false)
{
return false;
}
else
{
while ($row = $result->fetch_array(MYSQLI_ASSOC) )
{
$rows[]=$row;
}
}
return $rows;
}
function lastid()
{
return $this->qval("SELECT LAST_INSERT_ID()");
}
Usage example:
q('INSERT INTO USER(name, email) VALUES(?,?)', array('admin','admin#admin.com'));
$id = lastid();