Insert an array to MySQL database using PHP's prepared statements - php

I have an input array that I want to insert to database. I don't want to have 1 row in database for each item in the array. I want them all to go on same row. So this is my code:
<?php
session_start();
include('../../config/dbconf.php');
mysqli_select_db($conn, $webdb);
$stmt = $conn->prepare("INSERT INTO changelog (title, type, content, author, post_date) VALUES (?, ?, ?, ?, ?)");
$title = $_POST['title'];
$type = $_POST['type'];
$change = $_POST['change'];
$author = $_SESSION['waradmin'];
$date = time();
foreach($_POST['change'] as $key => $value) {
$changes = "<li>" . $change[$key] . "</li>";
}
$stmt->bind_param("sissi", $title, $type, $changes, $author, $date);
if($stmt->execute()) {
header('location: ../?p=dashboard');
}else{
echo "Error: " . $stmt->error;
}
$stmt->close();
?>
The query runs in database but only the first list item from the array... Do I need to use the implode function? I have never used it so if that is the only solution can someone show me how i use that in this query?

Instead of replacing variable value you have to concatenate
$changes = '';
foreach($_POST['change'] as $key => $value) {
$changes .= "<li>" . $change[$key] . "</li>";
}
And this is how to make a little more clean:
$changes = '';
foreach($_POST['change'] as $value) {
$changes .= '<li>' . $value . '</li>';
}

Related

How to print PDO CRUD Statements and Values of bindParams -PHP PDO

I am new to PDO PHP. I have created a post data function in order to achieve the insertion functionality. Here is my code.
public function PostData($conn, $table, $data)
{
try {
$query = "INSERT INTO " . $table . "(";
$arraylen = count($data);
$keyloopcount = 0;
foreach ($data as $key => $values) {
$query .= $key;
if ($keyloopcount != $arraylen - 1) {
$query .= ",";
}
$keyloopcount++;
}
$valloopcount = 0;
$query .= ") VALUES (";
foreach ($data as $key => $values) {
$query .= "':" . $key . "'";
if ($valloopcount != $arraylen - 1) {
$query .= ",";
}
$valloopcount++;
}
$query .= ")";
$stmt = $conn->prepare($query);
foreach ($data as $key => &$values) {
$stmt->bindParam(':'.$key, $values, PDO::PARAM_STR);
}
if ($stmt->execute()) {
$stmt->debugDumpParams();
echo "me";
} else {
echo "die";
}
} catch (PDOException $ex) {
echo $ex->getMessage();
}
}
When I execute this query. It doesn't show any exceptions. but when I look into my Database. It shows inserted records as follows.
I am wondering if there is a way I can debug what are the values in the binded params. I have also looked for $stmt->debugDumpParams(); as shown in the code. But it doesn't shows the values of params.
Need Guidance. TIA.
I sorted it out. I was making a silly mistake. The solution was so simple and easy.
Solution
The problem was lying in the part of the code.
foreach ($data as $key => $values) {
$query .= "':" . $key . "'";
if ($valloopcount != $arraylen - 1) {
$query .= ",";
}
$valloopcount++;
}
Changed the code to:
foreach ($data as $key => $values) {
$query .= ":" . $key;
if ($valloopcount != $arraylen - 1) {
$query .= ",";
}
$valloopcount++;
}
Resultant Query Before Amendment:
INSERT INTO cmp_categories(cat_name,cat_slug,cat_desc) VALUES (':cat_name',':cat_slug',':cat_desc')
Resultant Query AfterAmendment:
INSERT INTO cmp_categories(cat_name,cat_slug,cat_desc) VALUES (:cat_name,:cat_slug,:cat_desc)
More Clearly,
Removed ' from VALUES clause. ':cat_desc' => :cat_desc

php inserts only last array record into sql

I have working code, which inserts data into csv file. Here is a part of it:
if (isset($_POST['array'])) {
foreach ($_POST['array'] as $loop) {
$txt = $txt . $loop['name'] . ";" . $loop['email'];
$txt .="\n";
}
}
Instead of csv, i would like it to insert data into mysql database, so i have simply changed the code to:
if (isset($_POST['array'])) {
foreach ($_POST['array'] as $loop) {
$sql = "insert into persons (Name, Email)
values ('" . $loop['name'] . "', '" . $loop['email'] . "')";
}
}
Only the last record is saved into the persons table. There are no errors, but all the previous records except last are not inserted. Why?
Better way is only one time create insert
if (isset($_POST['array'])) {
$values = [];
$sql = "insert into persons (Name, Email) values ";
foreach ($_POST['array'] as $loop) {
$values[] = "('" . $conn->real_escape_string($loop['name']) . "', '" . $conn->real_escape_string($loop['email']) . "')";
}
if (!empty($values)) {
$conn->query($sql . implode(', ', $values));
}
}
The reason why it doesn't work is because you never execute your SQL query anywhere.
To execute the query you should first prepare the statement and then bind the params and execute.
// Your connection to DB
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'username', 'password', 'dbname');
$mysqli->set_charset('utf8mb4'); // always set the charset
if (isset($_POST['array'])) {
$stmt = $mysqli->prepare('INSERT INTO persons (Name, Email) VALUES (?,?)');
foreach ($_POST['array'] as $loop) {
$stmt->bind_param('ss', $loop['name'], $loop['email']);
$stmt->execute();
}
}
Please execute query inside the loop as given below
...
$conn = mysqli_connect($servername, $username, $password, $dbname);
...
if (isset($_POST['array'])) {
foreach ($_POST['array'] as $loop) {
$sql = "insert into persons (Name, Email)
values ('" . $loop['name'] . "', '" . $loop['email'] . "')";
$conn->query($sql);// Query should execute inside loop
}
}
I had the same issue inserting JSON arrays into MySQL and fixed it by putting the mysqli_stmt->execute() function inside the foreach
// loop through the array
foreach ($data as $row) {
echo "Data has been Uploaded successfully <br>";
// get the project details
$id = $row['id'];
$name = $row['name'];
$togglCid = $row['cid'];
// execute insert query
mysqli_stmt_execute($sql);
}
This means it executes the code after each loop
If you want to execute the query outside the loop
Try using as following
if (isset($_POST['array'])) {
$sql="";
foreach ($_POST['array'] as $loop) {
$sql .= "insert into persons (Name, Email)
values ('" . $loop['name'] . "', '" . $loop['email'] . "');\n";
}
}

How to use single for each loop for multiple array to update single sql statement

I want to use single for each for two array.
array 1 : has path of images (path is dynamic as per user need)
array 2: has values description field of each image (description is dynamic as per user need)
I want to insert both array in sql table using only one sql statement.
<?php $sql="INSERT INTO posts(title,description,category,createdBy,pictureURL,CreatedAt) VALUE ('$title',
'$description','$category','$creatdby','Admin/PostImages/$finalpath',now());";
$result = mysqli_query($conn,$sql);
if($result)
{
$upload_directory = 'PostImages/';
$field_values_array = $_REQUEST['desc'];
$x=0;
foreach($field_values_array as $value1){
foreach ( $_FILES['photo']['name'] AS $key => $value ){
//Move file to server directory
if(move_uploaded_file($_FILES["photo"]["tmp_name"][$x], $upload_directory . $_FILES["photo"]["name"][$x])){
$finalpath=$upload_directory . $_FILES["photo"]["name"][$x];
}
if (isset($_SESSION['p_id'])){
$p_id = $_SESSION["p_id"];
}
$sql1="INSERT INTO `postimages`(`p_id`,`description`, `img_path`) VALUES ('$p_id','$value1','$finalpath')";
$result1 = mysqli_query($conn,$sql1);
$x++;
}
}
header("Location: uploadpost_test.php");
}
else
{
echo "Error: " . $sql . "<br>" . $conn->error;
} ?>
I refactor and clean up your codes. Try this.
if(isset($_SESSION['p_id']))
{
$p_id = $_SESSION["p_id"];
}
$values = '';
$next = ',';
$len = count($field_values_array);
foreach($field_values_array as $x=>$value1)
{
if(move_uploaded_file($_FILES["photo"]["tmp_name"][$x], $upload_directory.$_FILES["photo"]["tmp_name"][$x]))
{
$tmp_name = $_FILES["photo"]["tmp_name"][$x];
$finalpath = $upload_directory.$tmp_name;
$next = $x >= $len-1 ? '' : $next;
$values .= "VALUES('$p_id','$value1','$finalpath')".$next;
}
}
$sql1="INSERT INTO `postimages`(`p_id`,`description`, `img_path`) $values";
$result1 = mysqli_query($conn,$sql1);

PHP Mysqli insert into database with large iterations

Below I have Php code that loops through an array and for each it checks if the value already exists in the database and if not, create it. The code itself is working but the loop itself can be insanely big, maximum of a couple tens thousand iterations.
How can I optimize this code? What to use and how to use. There should be a better way to insert this many times without looping through each individual.
foreach($arr as $value){
$checkID = mysqli_query($cenn, "SELECT item_id from items WHERE item_id = '$value'");
if (!$checkID) {
die("Query '$checkID' failed to execute for some reason");
}else{
if (mysqli_num_rows($checkID) > 0) {
$user = mysqli_fetch_array($checkID);
echo "item_id" . checkID . "exists already";
}
else{
echo "item_id: '$user_id' doesn't exist<br>";
$gw2Api = file_get_contents("https://api.guildwars2.com/v2/items/" . $user_id); //12452 30704
$gw2Api_result = json_decode($gw2Api,true);
/*Here would be some code to determine values that are being inserted*/
if (!array_key_exists("description",$gw2Api_result)) {
$description = 'No description available...';
} else{
if($gw2Api_result['description'] === ''){
$description = "No description available...";
} else {
$description = $gw2Api_result['description'];
}
}
$insertItem = "INSERT INTO items
(item_id, name, description,
AccountBindOnUse, AccountBound,
last_update
)
VALUES ('$user_id', '$gw2Api_result[name]', '$description',
'$AccountBindOnUse', '$AccountBound', CURRENT_TIMESTAMP)";
if ($cenn->query($insertItem) === true) {
echo "New record '$user_id' created successfully";
} else {
echo "Error: " . $sql . "<br>" . $cenn->error;
}
}
}
} // end foreach
The question: How to insert many values, new rows, into mysqli database as fast as possible.
Just use bulk insert.
Collect all the rows for insertion and pass it in one query.
echo 'hi';
if (!empty($arr)) {
echo 'ok';
$values = "'" . implode("', '", $arr) . "'";
$qExistingItemIds = mysqli_query($cenn, "SELECT item_id from items WHERE item_id IN($values)");
$existingItemIds = [];
while ($existingItemId = mysqli_fetch_array($qExistingItemIds)) {
$existingItemIds[] = $existingItemId['item_id'];
}
$arr = array_diff($arr, $existingItemIds);
$inserts = array();
$i = 0;
$ic = count($arr);
foreach ($arr as $value) {
$i++;
echo "item_id: $value doesn't exist<br>";
$gw2Api = file_get_contents("https://api.guildwars2.com/v2/items/" . $value); //12452 30704
$gw2Api_result = json_decode($gw2Api,true);
/*Here would be some code to determine values that are being inserted*/
if (!array_key_exists("description", $gw2Api_result)) {
$description = 'No description available...';
} else {
if ($gw2Api_result['description'] === '') {
$description = "No description available...";
} else {
$description = $gw2Api_result['description'];
}
}
$inserts[] = "
('$value', '$gw2Api_result[name]', '$description', '$AccountBindOnUse', '$AccountBound', CURRENT_TIMESTAMP)
";
if ($i == 50 OR $i == $ic) {
$inserts = implode(",", $inserts);
$insert = "
INSERT INTO items
(item_id, name, description, AccountBindOnUse, AccountBound, last_update)
VALUES
$inserts
";
if ($cenn->query($insert) === true) {
echo 'great';
echo "New records created successfully";
} else {
echo "Error: " . $sql . "<br>" . $cenn->error;
}
$ic -= 50;
$i = 0;
$inserts = array();
}
}
}
so now we have only 2 queries. not thousands
details about bulk insert:
http://www.geeksengine.com/database/data-manipulation/bulk-insert.php
If you use prepared statement you should reduce the round trips to the database server and only compile and optimise each query once instead of Number_of_inputs * 2 queries. This should reduce the workload.
I would be very interested to know by how much.
$sql = "SELECT item_id from items WHERE item_id = ?";
$db_select = $cenn->prepare($sql);
if ( ! $db_select ) {
echo $cenn->error;
exit;
}
$sql_insert = "INSERT INTO items
(item_id, name, description,
AccountBindOnUse, AccountBound, last_update)
VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP)";
$db_insert = $cenn->prepare($sql);
if ( ! $db_insert ) {
echo $cenn->error;
exit;
}
foreach($arr as $value){
$db_select->bind_param('i', $value);
$res = $db_select->execute()
if ( $res === FALSE ) {
echo $cenn->error;
exit;
}
if ($db_select->num_rows > 0) {
// dont bother fetching data we already know all we need to
$user = $db_select->free();
echo "item_id $value exists already";
} else {
echo "item_id: $value doesn't exist<br>";
$gw2Api = file_get_contents("https://api.guildwars2.com/v2/items/" . $value);
$gw2Api_result = json_decode($gw2Api,true);
if ( ! array_key_exists("description",$gw2Api_result)
|| $gw2Api_result['description'] === '') {
$description = 'No description available...';
} else{
$description = $gw2Api_result['description'];
}
$db_insert->bind_param('issss', $value, $gw2Api_result[name],
$description, $AccountBindOnUse,
$AccountBound)
if ($cenn->query($insertItem) === true) {
echo "New record $value' created successfully";
} else {
echo "Error: " . $sql_insert . "<br>" . $cenn->error;
}
}
} // end foreach

Moving html table content to sql database

I've got a table (grabbed from another website using php) but now I want to import it's content into my database (instead of just printing out the table).
This is the printout (http://i.stack.imgur.com/NnbAo.png) from the table using the following code:
<?php
$uitvoer = getTable();
echo "<table">;
foreach ($uitvoer as $row) {
echo "<tr>";
foreach ($row as $col) {
echo "<td>" . $col . "</td>";
}
echo "</tr>";
}
echo"</table>";
?>
And when I try this nothing happens to my database:
<?php
$con = mysqli_connect("mysql1.000webhost.com","a2902119_lowavol","pswd")
$uitvoer = getTable();
foreach ($uitvoer as $row) {
foreach ($row as $col) {
$query += "'" . $col . "', ";
}
$sql="INSERT INTO test (cel1, cel2, cel3, cel4, cel5, cel6, cel7, cel8, cel9) VALUES ($query)";
mysqli_query($con, $sql);
}
?>
I have little to no knowledge about PHP. Thanks for helping me!
The concatenation operator for PHP is (.) and not (+)
<?php
$con = mysqli_connect("mysql1.000webhost.com","a2902119_lowavol","pswd")
$uitvoer = getTable();
foreach ($uitvoer as $row) {
$query = array();
$insert = "";
$insert_values = "";
foreach ($row as $col) {
$query[] = $col;
}
$insert_values = implode("','", $query) ;
$insert = "'".$insert_values."'";
$sql = "INSERT INTO test (cel1, cel2, cel3, cel4, cel5, cel6, cel7, cel8, cel9) VALUES ($insert)";
mysqli_query($con, $sql);
}
?>
your query will look like this:
INSERT INTO test (....) VALUES (val, val, val, )
which is obviously a syntax error... try and add the fields to an array instead:
foreach ($uitvoer as $row) {
$fields = array();
foreach ($row as $col) {
$fields[] = $col; // TODO: add escaping!
}
// now you can build the values list with implode
$values = implode(', ', $fields);
$sql="INSERT INTO test (...) VALUES ($values)";
See the docs about implode() for more info.
Use a prepared statement:
$sql="INSERT INTO test (cel1, cel2, cel3, cel4, cel5, cel6, cel7, cel8, cel9) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = mysqli_prepare($con, $sql);
mysqli_stmt_bind_param($stmt, "sssssssss", $row[0], $row[1], $row[2], $row[3], $row[4], $row[5], $row[6], $row[7], $row[8]);
foreach ($uitvoer as $row) {
mysqli_stmt_execute($stmt);
}
Try echo-ing $sql. I think there is a comma in the end.
Use
$query = substr($query, 0, strlen($query) - 1)
in order to remove the last character of $query
(edited the command)

Categories