PHP - Converting PDO to normal code - php

I was wondering if someone could help me.
Im trying to integrate some code into my application, the code that i need to integrate is written with PDO statements and i have no idea how it goes.
I was wondering if someone could help me convert it.
The code is as follows
$sql = "insert into message2 (mid, seq, created_on_ip, created_by, body) values (?, ?, ?, ?, ?)";
$args = array($mid, $seq, '1.2.2.1', $currentUser, $body);
$stmt = $PDO->prepare($sql);
$stmt->execute($args);
if (empty($mid)) {
$mid = $PDO->lastInsertId();
}
$insertSql = "insert into message2_recips values ";
$holders = array();
$params = array();
foreach ($rows as $row) {
$holders[] = "(?, ?, ?, ?)";
$params[] = $mid;
$params[] = $seq;
$params[] = $row['uid'];
$params[] = $row['uid'] == $currentUser ? 'A' : 'N';
}
$insertSql .= implode(',', $holders);
$stmt = $PDO->prepare($insertSql);
$stmt->execute($params);

You shoudl use PDO unles for some technical reason you cant. If you dont know it, learn it. Maybe this will get you started:
/*
This the actual SQL query the "?" will be replaced with the values, and escaped accordingly
- ie. you dont need to use the equiv of mysql_real_escape_string - its going to do it
autmatically
*/
$sql = "insert into message2 (mid, seq, created_on_ip, created_by, body) values (?, ?, ?, ?, ?)";
// these are the values that will replace the ?
$args = array($mid, $seq, '1.2.2.1', $currentUser, $body);
// create a prepared statement object
$stmt = $PDO->prepare($sql);
// execute the statement with $args passed in to be used in place of the ?
// so the final query looks something like:
// insert into message2 (mid, seq, created_on_ip, created_by, body) values ($mid, $seq, 1.2.2.1, $currentUser, $body)
$stmt->execute($args);
if (empty($mid)) {
// $mid id is the value of the primary key for the last insert
$mid = $PDO->lastInsertId();
}
// create the first part of another query
$insertSql = "insert into message2_recips values ";
// an array for placeholders - ie. ? in the unprepared sql string
$holders = array();
// array for the params we will pass in as values to be substituted for the ?
$params = array();
// im not sure what the $rows are, but it looks like what we will do is loop
// over a recordset of related rows and do additional inserts based upon them
foreach ($rows as $row) {
// add a place holder string for this row
$holders[] = "(?, ?, ?, ?)";
// assign params
$params[] = $mid;
$params[] = $seq;
$params[] = $row['uid'];
$params[] = $row['uid'] == $currentUser ? 'A' : 'N';
}
// modify the query string to have additional place holders
// so if we have 3 rows the query will look like this:
// insert into message2_recips values (?, ?, ?, ?),(?, ?, ?, ?),(?, ?, ?, ?)
$insertSql .= implode(',', $holders);
// create a prepared statment
$stmt = $PDO->prepare($insertSql);
// execute the statement with the params
$stmt->execute($params);
PDO really is better. It has the same functionality as MySQLi but with a consistent interface across DB drivers (ie. as long as your SQL is compliant with a different database you can theoretically use the exact same php code with mysql, sqlite, postresql, etc.) AND much better parameter binding for prepared statements. Since you shouldnt be using the mysql extension any way, and MySQLi is more cumbersome to work with than PDO its really a no-brainer unless you specifically have to support an older version of PHP.

Related

Prevent Duplicate Entries in PHP MySQL

I have the following in my PHP.
$stmt = $conn->prepare("INSERT IGNORE INTO savesearch (user, searchedFor, sortOrder, buildURLString, aspectFilters, oneSignalId, totalEntries)
VALUES (?, ?, ?, ?, ?, ?, ?)");
$stmt->bind_param("sssssss", $user, $searchedFor, $sortOrder, $buildURLString, $aspectFilters, $oneSignalId, $totalEntries);
// set parameters and execute
$user = $_POST['user'];
$searchedFor = $_POST["searchedFor"];
$sortOrder = $_POST["sortOrder"];
$buildURLString = $_POST["buildURLString"];
$aspectFilters = $_POST["aspectFilters"];
$oneSignalId = $_POST["oneSignalId"];
$totalEntries = $_POST["totalEntries"];
if ($stmt->execute()) {
$output->success = true;
echo json_encode($output);
} else {
$error->error = mysqli_error($conn);
echo json_encode($error);
}
However, IGNORE is not being picked up, it continues to add entries. Is there another good way to fix this?
Id like to see if the USER and the URL is the same, dont add, echo duplicate entry.
IGNORE is actually mostly for the opposite of what you want here. Instead, you can amend your MySQL table something like:
ALTER TABLE savesearch ADD UNIQUE KEY(user, buildURLString)
Then remove your IGNORE keyword

Inserting thousands of rows in one query MySQL using PHP

I have tried whole day (again) but with error trying to insert in total of over billion of rows while inserting about 10k within one query. I want to use prepared statements to do this with MySQL, using innoDB tables. Hardware resources are not a problem, problem has all the time been indexing and one row / insert.
Do not say that I should use straight from list methods since I need to do some calculations before inserting. Input comes from file.
So I have a big while loop, looping text file lines and that's working fine.
I currently do it with inserting one per query.
$stmt = $conn->prepare("INSERT INTO $tableName(row1, row2, row3) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $str1, $str2, $str3);
$stmt->execute();
I have looked at examples doing it like so:
$stmt = $conn->prepare("INSERT INTO $tableName(row1, row2, row3) VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?), (?, ?, ?) ..... ");
But I need to construct this to for like 5-10k rows for single query.
If someone has done something like this before, please give some reference to work with.
Thanks in advance!
The whole idea of a prepared query is that it reduces the overhead of setting up the query each time it's run – prepare once, execute repeatedly. That means there's not going to be a huge amount of difference (from the POV of the database) between running a prepared statement in a loop, or passing one giant query.
You don't include your whole code here, but an error that many people make is to include the statement preparation in the loop. Don't make that mistake! Something like this will be most efficient:
// these need a value before being used in bind_param
$str1 = $str2 = $str3 = "";
$stmt = $conn->prepare("INSERT INTO $tableName(row1, row2, row3) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $str1, $str2, $str3);
while ($we_have_data) {
$str1 = "foo";
$str2 = "bar";
$str3 = "baz";
$stmt->execute();
}
Though I always recommend using PDO prepared statements, as you get to avoid the potential mess of binding parameters:
// assuming $conn is a PDO object now
$stmt = $conn->prepare("INSERT INTO $tableName(row1, row2, row3) VALUES (?, ?, ?)");
while ($we_have_data) {
$str1 = "foo";
$str2 = "bar";
$str3 = "baz";
$stmt->execute([$str1, $str2, $str3]);
}
Maybe because limit executing time from server. Try to use insert batch.
Add to array
$i = 0;
.. looping
$i++;
$mark[] = '(?,?,?)';
$val[] = $str1.",".$str2.",".$str3;
// check when 1k record
if($i == 1000){
$stmt = $conn->prepare("INSERT INTO ? (row1, row2, row3) VALUES ".implode(',', $mark);
$stmt->bind_param("sss", implode(',', $val));
$stmt->execute();
$mark = []; $val = []; $i = 0; // reset
}

Use lastInsertId() multiple times on different queries in transaction

So I've been trying to find an answer but I don't think there is one that is specified to what I am trying to do. I will start with my sample of code
file.php
$q = "INSERT INTO ".PORTAL_DB.".resource_file (company__id, rf_category__id, title, file_name, description, path, upload_by, has_quiz)
SELECT ?, ?, ?, CONCAT(MAX(id)+1, '.', '$extension'), ?, ?, ?, ? FROM ".PORTAL_DB.".resource_file";
$stmt = $CONN->prepare($q);
$filename = 0;
$resource_file__id = 0;
if($stmt->execute(array($company__id, $rf_category__id, $title, $description, "assets/$uploadFolder/", USER, $has_quiz))){
$filename = $CONN->lastInsertId();
$resource_file__id = $filename;
}
if(!empty($quiz)){
$passing_score = $quiz->passing_score;
if(!is_numeric($passing_score) or ($passing_score < 0) or $passing_score > 100){
$CONN->rollback();
throw new Exception("Invalid passing score value for quiz, please fix");
}
$q = "INSERT INTO ".PORTAL_DB.".rf_quiz (resource_file__id, passing_score)
VALUES(?, ?)";
$stmt = $CONN->prepare($q);
$rf_quiz__id = 0;
$stmt->execute(array($resource_file__id, $passing_score));
print_r($CONN->lastInsertId);
exit;
$question_ids = array();
foreach($quiz as $qz){
$question = $qz->question;
//print_r($qz);
$q = "INSERT INTO ".PORTAL_DB.".rf_quiz_question (rf_quiz__id, question)
VALUES(?, ?)";
$stmt = $CONN->prepare($q);
if($stmt->execute(array($rf_quiz__id, $question))){
array_push($question_ids, $CONN->lastInsertId);
}
}
//print_r($question_ids);
exit; // using this for testing only
}
explanation
The above code is called after $CONN->beginTransaction() so that I can manage errors easier. From what I understand you can call the stamtement $CONN->lastInsertId() multiple times without issue, however I can get the first id which is stored under the variable $resource_fild__id then when we go down to the $rf_quiz__id variable, even if the call is successful, I get nothing and it causes an error. I want to be able to do all of this in one transaction for the ease of the coding process and organization.
I hope someone can point me in the right direction, or at least be able to tell me what I am doing wrong so that I can find a fast solution!
Thank you for all help in advance.

Multiple mysqli prepared statements with transactions

I'm trying to figure out how to use sql transactions with mysqli prepared statements. I haven't been able to find any examples that use multiple prepared statements (that aren't OO), so I'm not really sure how to use transactions with them.
This is the closest I could figure:
mysqli_autocommit($database, FALSE);
$transferq = 'INSERT INTO money (user_id, bank, onhand, type, amount, source) VALUES (?, ?, ?, ?, ?, ?)';
$transferstmt = mysqli_stmt_init($database);
mysqli_stmt_prepare($transferstmt, $transferq);
mysqli_stmt_bind_param($transferstmt, 'iiisis', $userid, $newbank, $newmoney, $type, $amount, $source);
mysqli_stmt_execute($transferstmt);
$insertq = 'UPDATE users SET money=?, bank=? WHERE user_id=' . $userid . ' LIMIT 1';
$insertstmt = mysqli_stmt_init($database);
mysqli_stmt_prepare($insertstmt, $insertq);
mysqli_stmt_bind_param($insertstmt, 'ii', $newmoney, $newbank);
mysqli_stmt_execute($insertstmt);
mysqli_commit($database);
But, I have no idea if that would even work. My biggest issue, though, is I'm not sure how to check if the queries failed or not (and therefore whether or not to commit). I saw an example that I think did something like
if(mysqli_stmt_execute($stmt)){
mysqli_commit($database);
}else{
mysqli_rollback($database);
}
But I can't really do that since I have multiple prepared statements to execute.
How is this supposed to work?
Maybe I did not understand your question, but what about this?
mysqli_autocommit($database, FALSE);
$transferq = 'INSERT INTO money (user_id, bank, onhand, type, amount, source) VALUES (?, ?, ?, ?, ?, ?)';
$transferstmt = mysqli_stmt_init($database);
mysqli_stmt_prepare($transferstmt, $transferq);
mysqli_stmt_bind_param($transferstmt, 'iiisis', $userid, $newbank, $newmoney, $type, $amount, $source);
if (not mysqli_stmt_execute($transferstmt) ){
mysqli_rollback($database);
return;
}
$insertq = 'UPDATE users SET money=?, bank=? WHERE user_id=' . $userid . ' LIMIT 1';
$insertstmt = mysqli_stmt_init($database);
mysqli_stmt_prepare($insertstmt, $insertq);
mysqli_stmt_bind_param($insertstmt, 'ii', $newmoney, $newbank);
if (not mysqli_stmt_execute($insertstmt) ){
mysqli_rollback($database);
return;
}
mysqli_commit($database);
The next level if form of this object-oriented using of mysqli or PDO (without transactions, as example of way of work with database):
class my_database{
private static $inner_link_to_driver;
protected static function factory( ){
if (not static::$inner_link_to_driver){
static::$inner_link_to_driver = new ...(USER, SERVER, PASSWD, PORT);
}
return static::$inner_link_to_driver;
}
public static function do_something($params, &$message ){
$query = "...";
$stmt = static::factory()->prepare($query);
if (not $stmp ){
$message = 'Error prepare query '.$query.PHP_EOL.static::factory()-> ..(get_error);
return FALSE;
}
if (not $stmt->execute($params) ){
$message = 'Error execute query '.$query.PHP_EOL.static::factory()-> ..(get_error);
return FALSE;
}
return TRUE;
}
}

Query isn't getting executed

Can some onw please explain what is wrong with this ... this worked completely fine with procedural php
function foo(){
$incomingtime = date('Y-m-d H:i:s', time());
$stmt = $db->stmt_init();
$id = "Abc123" ;
$u_id = 1;
$c_id = 1;
$query = "INSERT INTO table (indate, myid, uniqueid, commonid)
VALUES (?, ?, ?, ?)";
$stmt = $db->prepare($query);
$stmt->bind_param('ssii', $incomingtime, $id, $u_id, $c_id);
$stmt->execute();
printf("Affected rows (UPDATE): %d\n", $db->affected_rows); // Always return 1
$stmt->close();
}
But nothing goes in the database.
Datatype in mysql db for indate is datetime
There's several issues with this code.
$stmt_4 is used before it's defined.
$u_id and $c_id are both defined then not used.
Trying to execute $stmt without supplying parameters.
$db is not defined.
$id is not defined.
If you are trying to convert working code to a function make sure that either the function gets these passed in as an argument, they are marked as global or the function creates/ retrieves them.
Check changing:
$query = "INSERT INTO table (indate, myid, uniqueid, commonid)
VALUES (?, ?, ?, ?)";
$stmt = $db->prepare($query);
$stmt->bind_param('ssii', $incomingtime, $id, $u_id, $c_id);
$u_id = 1;
$c_id = 1;
$stmt->execute();
to:
$u_id = 1;
$c_id = 1;
$query = "INSERT INTO table (indate, myid, uniqueid, commonid)
VALUES (CURRENT_TIMESTAMP, ?, ?, ?)"
$stmt = $db->prepare($query);
$stmt->execute(array($id, $u_id, $c_id));
NOTE: I deleted the parameter ssii because it's not considered in the query. It only expects 4 parameters.

Categories