filter apostrophe out of xml variables - php

hi, i work with a small xml script that filters all entries in a database. My problem is, that in the names of some xml strings are apostrophs that i need to filter in a mysql database. but when i run the script, all data es there, except for them with apostrophe. heres my code:
include 'new.php'; //include xml file
$haus = new SimpleXMLElement($xmlstr);
´
foreach ($haus->features as $features) {
foreach ($features->properties as $properties) {
$name = $properties->name;
$insert = $mysqli->query("INSERT INTO locations (name)
VALUES ('$name')");
echo $mysqli->affected_rows;
}
}
is there a way to get the apostrophe in the database with php?

Use a prepared statement which means you don't have to worry about quotes. This will also protect you from SQL Injection. There will also be a slight performance benefit because you can create the prepared statement once, then execute it many times without having to send the whole query to the MySQL engine over and over.
$count = 0; // if you want to check how many rows were inserted
if($stmt = $mysqli->prepare('INSERT INTO locations (name) VALUES (?)')){
foreach ($haus->features as $features) {
foreach ($features->properties as $properties) {
$name = $properties->name;
$stmt->bind_param('s', $name);
if($stmt->execute()){
$count++;
}
}
}
}
echo 'total inserted: ' . $count;

Related

SQL INSERT function with PHP only

edit I changed the code to the suggestion answer, all snippets now updated
currently I am playing around with PHP. Therefore I am trying to build a programm which can execute SQL commands. so, what I am trying is to write some functions which will execute the query. But I came to a point where I coundn't help myself out. My trouble is, for the INSERT INTO command, I want to give an array, containing the Data that shall be inserted but I simply can't figure out how to do this.
Here is what I got and what I think is relevant for this operation
First, the function I want to create
public function actionInsert($data_values = array())
{
$db = $this->openDB();
if ($db) {
$fields = '';
$fields_value = '';
foreach ($data_values as $columnName => $columnValue) {
if ($fields != '') {
$fields .= ',';
$fields_value .= ',';
}
$fields .= $columnName;
$fields_value .= $columnValue;
}
$sqlInsert = 'INSERT INTO ' . $this->tabelle . ' (' . $fields . ') VALUES (' . $fields_value . ')';
$result = $db->query($sqlInsert);
echo $sqlInsert;
if ($result) {
echo "success";
} else {
echo "failed";
}
}
}
and this is how I fil the values
<?php
require_once 'funktionen.php';
$adresse = new \DB\Adressen();
$adresse->actionInsert(array('nachname'=>'hallo', 'vorname'=>'du'));
My result
INSERT INTO adressen (nachname,vorname) VALUES (hallo,du)failed
What I wish to see
success
and of course the freshly insertet values in the database
There are a few things to consider when you are working with relational databases without using PDO:
What is the database that you are using.
It's your decision to choose from MySQL, postgreSQL, SQLite and etc., but different DBs generally have different syntax for inserting and selecting data, as well as other operations. Also, you may need different classes and functions to interact with them.
That being said, did you checkout the official manual of PHP? For example, An overview of a PHP application that needs to interact with a MySQL database.
What is the GOAL you are trying to accomplish?
It's helpful to construct your SQL first before you are messing around with actual codes. Check if your SQL syntax is correct. If you can run your SQL in your database, then you can try to implement your code next.
What's the right way to form an SQL query in your code?
It's okay to mess around in your local development environment, but you should definitely learn how to use prepared statements to prevent possible SQL injection attacks.
Also learn more about arrays in PHP: Arrays in PHP. You can use key-value pairs in a foreach loop:
foreach ($keyed_array as $key => $value) {
//use your key and value here
}
You don't need to construct your query in the loop itself. You are only using the loop to construct the query fields string and VALUES string. Be very careful when you are constructing the VALUES list because your fields can have different types, and you should add double quotes around string field values. And YES, you will go through all these troubles when you are doing things "manually". If you are using query parameters or PDO or any other advanced driver, it could be much easier.
After that, you can just concatenate the values to form your SQL query.
Once you get more familiar with the language itself and the database you are playing with, you'll definitely feel more comfortable. Good luck!
Is this inside of a class? I assume the tabelle property is set correctly.
That said, you should correct the foreach loop, that's not used correctly:
public function actionInsert($data_values) //$data_values should be an array
{
$db = $this->openDB();
if ($db) {
foreach ($data_values as $data){
// $data_values could be a bidimensional array, like
// [
// [field1=> value1, field2 => value2, field3 => value3],
// [field1=> value4, field2 => value5, field3 => value6],
// [field1=> value7, field2 => value8, field3 => value9],
// ]
$fields = Array();
$values = Array();
foreach($data as $key => $value){
array_push($fields,$key);
array_push($values,"'$value'");
}
$sqlInsert = 'INSERT INTO ' . $this->tabelle . ' (' . join(',',$fields) . ') VALUES (' . join(',',$values) . ')';
$result = $db->query($sqlInsert);
echo $sqlInsert;
if ($result) {
echo "success";
} else {
echo "failed";
}
}
}
This is a rather basic approach, in which you cycle through you data and do a query for every row, but it isn't very performant if you have big datasets.
Another approach would be to do everything at once, by mounting the query in the loop and sending it later (note that the starting array is different):
public function actionInsert($data_values) //$data_values should be an array
{
$db = $this->openDB();
if ($db) {
$vals = Array();
foreach ($data_values['values'] as $data){
// $data_values could be an associative array, like
// [
// fields => ['field1','field2','field3'],
// values => [
// [value1,value2,value3],
// [value4,value5,value6],
// [value7,value8,value9]
// ]
// ]
array_push('('.join(',',"'$data'").')',$vals);
}
$sqlInsert = 'INSERT INTO ' . $this->tabelle . ' (' . join(',',$data_values['fields']) . ') VALUES '.join(' , ',$vals);
$result = $db->query($sqlInsert);
echo $sqlInsert;
if ($result) {
echo "success";
} else {
echo "failed";
}
}
By the way dragonthought is right, you should do some kind of sanitizing for good practice even if you don't make it public.
Thanks to #Eagle L's answer, I figured a way that finally works. It is diffrent from what I tryed first, but if anyone having similar troubles, I hope this helps him out.
//get the Values you need to insert as required parameters
public function actionInsert($nachname, $vorname, $plz, $wohnort, $strasse)
{
//database connection
$db = $this->openDB();
if ($db) {
//use a prepared statement
$insert = $db->prepare("INSERT INTO adressen (nachname, vorname, plz, wohnort, strasse) VALUES(?,?,?,?,?)");
//fill the Values
$insert->bind_param('ssiss', $nachname, $vorname, $plz, $wohnort, $strasse);
//but only if every Value is defined to avoid NULL fields in the Database
if ($vorname && $nachname && $plz && $wohnort && $strasse) {
edited
$inserted = $insert->execute(); //added $inserted
//this is still clumsy and user unfriendly but serves my needs
if ($inserted) {//changed $insert->execute() to $inserted
echo 'success';
} else {
echo 'failed' . $inserted->error;
}
}
}
}
and the Function call
<?php
require_once 'funktionen.php';
$adresse = new \DB\Adressen();
$adresse->actionInsert('valueWillBe$nachname', 'valueWillBe$vorname', 'valueWillBe$plz', 'valueWillBe$wohnort', '$valueWillBe$strasse');

In PDO prepare statement, for multiple insert query executing twice.why?

database.php: //database class file
public function multipleInsert($table,$attrArray,$valuesArray) {
$sql = "INSERT INTO ".$table."(";
$array =[];
$appendValues = "";
$valuesInArray = "";
foreach ($attrArray as $key => $value) {
$sql.="".$value.", ";
}
$sql = substr_replace($sql,") VALUES ",strlen($sql)-2);
foreach ($valuesArray as $valArr) {
$valuesInArray.= "(";
foreach ($valArr as $key => $value) {
array_push($array, $value);
$valuesInArray.="?,";
}
$appendValues.= substr_replace($valuesInArray,"),",strlen($valuesInArray)-1);
$valuesInArray = "";
}
$appendValues = substr_replace($appendValues,"",strlen($appendValues)-1);
$sql.=$appendValues;
//die($sql);
$result = $this->executeQueryPRE($sql,$array);
return $result;
}
private function executeQueryPRE($sql,$arr) {
try{
$executeSQL = $this->Connection->prepare($sql);
print_r($executeSQL);die();
$executeSQL->execute($arr);
if($executeSQL) {
if($this->Connection->lastInsertId())
return $this->Connection->lastInsertId();
else
return true;
}
else
return false;
}
catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
}
sample.php // sample file which utilizing multiple insert query
require_once("database.php");
$Database = new Database;
$arr = ["ct_name","ct_num","ct_status"];
$arr1 = [["x","1234567890",1],["y","1234567890",1],["z","1234567890",1],["a","1234567890",1]];
$Database->multipleInsert("contact",$arr,$arr1);
Using PDO prepare statement, I am trying develop a dynamic multiple insert query. when I try to execute it, the values are getting inserted into table twice. I have gone for print_r($executeSQL) and die() option before executing it showed me a proper multiple insertion query as below.
PDOStatement Object ( [queryString] => INSERT INTO contact(ct_name,
ct_num, ct_status) VALUES (?,?,?),(?,?,?),(?,?,?),(?,?,?) )
why is it inserting twice and what is the reason and how can I overcome with this problem ?
Not an answer to your actual question but maybe to the actual problem you want to solve:
I don't think this string concat stuff is worth any trouble.
Takes longer for the php script to execute, pollutes the MySQL query cache, is error prone.
Therefore unless you can point to a very,very specific problem I think it loses on all points against: Just prepare a statement and execute it multiple times.
<?php
/*
table must be a valid table identifier
columns must be an array of valid field identifiers
recordData is an array of records, each itself an array of corresponding values for the fields in $columns
recordData is the only parameter for which proper encoding is taken care of by this function
*/
function foo($table, $columns, $recordData) {
$query = sprintf('
INSERT INTO %s (%s) VALUES (%s)
',
$table,
join(',', $columns) /* put in the field ids like a,b,c,d */,
join(',', array_pad(array(), count($columns), '?')) /* put in a corresponding number of ? placeholders like ?,?,?,? */
);
// resulting query string looks like INSERT INTO tablename (a,b,c,d) VALUES (?,?,?,?)
// let the MySQL server prepare that query
$stmt = $yourPDOInstance->prepare($query);
// it might fail -> check if your error handling is in place here....
// now just iterate through the data array and use each record as the data source for the prepapred statement
// this will (more or less) only transmit the statement identifier (which the MySQL server returned as the result of pdo::prepare)
// and the actual payload data
// .... as long as $yourPDOInstance->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); has been set somewhere prior to the prepare....
foreach( $recordData as $record ) {
$stmt->execute( $record );
// might fail, so again: check your error handling ....
}
}
$cols = ["ct_name","ct_num","ct_status"];
$data = [
["x","1234567890",1],
["y","1234567890",1],
["z","1234567890",1],
["a","1234567890",1],
];
foo("contact", $cols, $data);
(script is tested by php -l only; no warranty)
see also: http://docs.php.net/pdo.prepared-statements

How to use php array in a Prepared Statement for SQL IN Operator using SQLi? [duplicate]

This question already has answers here:
Can I bind an array to an IN() condition in a PDO query?
(23 answers)
Closed 8 years ago.
This is my code:
if(isset($_POST['abc']))
{
$things['abc'] = mysqli_real_escape_string($connect, implode("','", $_POST['abc']));
$result = mysqli_query($connect, "SELECT * FROM this_list WHERE abc_column IN ('{$things['abc']}')");
if (!$result)
{
echo "Error fetching results: " . mysqli_error();
}
else
{
while ($row = mysqli_fetch_array($result))
{
$abc[] = $row['description'];
}
}
}
The above code uses mysqli_real_escape_string(), and $things is an array with checkbox values that is received via POST. This array contains the list of strings separated by comma that I am using in the query.
When I was searching on the net, I noticed that some people say mysqli_real_escape_string() may prevent sql injection, I was thinking maybe prepared statement for checkbox values might be more safer against sql injection.
I have used prepared statement with separate parameters to prevent sql injection. But I am stuck on this one and I dont know how to change the above code to a prepare() statement since it uses an array $things['abc']. I tried searching and everytime I search array in prepared statement, I am getting info on Java, etc.. Can someone enlighten me on how I can do this with php please?
EDIT:
After the help from onetrickpony code below, this is what I have now:
if(isset($_POST['abc']))
{
$ph = rtrim(str_repeat('?,', count($_POST['abc'])), ',');
$query = sprintf("SELECT col1 FROM abc_table WHERE col2 IN (%s)", $ph);
$stmt = mysqli_prepare($connect, $query);
// bind variables
$params = array();
foreach($_POST['abc'] as $v)
$params[] = &$v;
array_unshift($params, $stmt, str_repeat('s', count($_POST['abc']))); // s = string type
call_user_func_array('mysqli_stmt_bind_param', $params);
mysqli_stmt_execute($stmt);
// Get the data result from the query.
mysqli_stmt_bind_result($stmt, $col1);
/* fetch values and store them to each variables */
while (mysqli_stmt_fetch($stmt)) {
$name[] = $col1;
echo $name;
}
//loop to echo and see whats stored in the array above
foreach($name as $v) {
echo $v;
}
// Close the prepared statement.
$stmt->close();
}
In the above code, the sqli method for prepare statement seems to work which is great. However, when I use the mysqli_stmt_bind_result(), the $name[] array inside the while loop only seems to print the last row.
UPDATE:
onetrickpony's code with the mysqli method for using php array in a Prepared Statement worked fine and it was a very good approach he had suggested. However, I have been having nightmare with the second half of the code which is trying to get the fetched array results to work. After trying for more than a day, I have given up on that and I have made the switch to PDO. Again onetrickpony's advise below was totally worth it. Making the switch to PDO made the code so much easier and simpler and couldnt believe it.
Try this:
// build placeholder string (?,?...)
$ph = rtrim(str_repeat('?,', count($_POST['abc'])), ',');
$query = sprintf("SELECT * FROM this_list WHERE abc_column IN (%s)", $ph);
$stm = mysqli_prepare($connect, $query);
// bind variables (see my notes below)
$params = array();
foreach($_POST['abc'] as $v)
$params[] = &$v;
// s = string type
array_unshift($params, $stm, str_repeat('s', count($_POST['abc'])));
call_user_func_array('mysqli_stmt_bind_param', $params);
mysqli_stmt_execute($stm);
It appears that mysqli_stmt_bind_param cannot be called multiple times to bind multiple variables. And even worse, it requires referenced variables. I'd recommend you switch to PDO, just because of these limitations that force you to write ugly code :)

php PDO insert batch multiple rows with placeholders

I am looking to do multiple inserts using PHP PDO.
The closest answer I have found is this one
how-to-insert-an-array-into-a-single-mysql-prepared-statement
However the example thats been given uses ?? instead of real placeholders.
I have looked at the examples on the PHP doc site for place holders
php.net pdo.prepared-statements
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
Now lets say I wanted to achieve the above but with an array
$valuesToInsert = array(
0 => array('name' => 'Robert', 'value' => 'some value'),
1 => array('name' -> 'Louise', 'value' => 'another value')
);
How would I go about it with PDO and multiple inserts per transaction?
I imagine it would start of with a loop?
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
foreach($valuesToInsert as $insertRow){
// now loop through each inner array to match binded values
foreach($insertRow as $column => value){
$stmt->bindParam(":{$column}", value);
}
}
$stmt->execute();
However the above does not work but hopefully will demonstrate what im trying to achieve
First of all, ? symbols are real place-holders (most drivers allow to use both syntaxes, positional and named place-holders). Secondly, prepared statements are nothing but a tool to inject raw input into SQL statements—the syntax of the SQL statement itself is unaffected. You already have all the elements you need:
How to insert multiple rows with a single query
How to generate SQL dynamically
How to use prepared statements with named place-holders.
It's fairly trivial to combine them all:
$sql = 'INSERT INTO table (memberID, programID) VALUES ';
$insertQuery = [];
$insertData = [];
$n = 0;
foreach ($data as $row) {
$insertQuery[] = '(:memberID' . $n . ', :programID' . $n . ')';
$insertData['memberID' . $n] = $memberid;
$insertData['programID' . $n] = $row;
$n++;
}
if (!empty($insertQuery)) {
$sql .= implode(', ', $insertQuery);
$stmt = $db->prepare($sql);
$stmt->execute($insertData);
}
I'm assuming you are using InnoDB so this answer is only valid for that engine (or any other transaction-capable engine, meaning MyISAM isn't included).
By default InnoDB runs in auto-commit mode. That means each query is treated as its own contained transaction.
To translate that to something us mortals can understand, it means that every INSERT query you issue will force hard-disk to commit it by confirming it wrote down the query information.
Considering how mechanical hard-disks are super slow since their input-output operation per second is low (if I'm not mistaken, the average is 300ish IO's), it means your 50 000 queries will be - well, super slow.
So what do you do? You commit all of your 50k queries in a single transaction. It might not be the best solution for various purposes but it'll be fast.
You do it like this:
$dbh->beginTransaction();
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
foreach($valuesToInsert as $insertRow)
{
// now loop through each inner array to match bound values
foreach($insertRow as $column => value)
{
$stmt->bindParam(":$column", value);
$stmt->execute();
}
}
$dbh->commit();
A little modifications in solution provided by N.B
$stmt->execute() should be outside of inner loop because you may have one or more columns that need to bind before calling $stmt->execute() else you 'll get exception "Invalid parameter number: number of bound variables does not match number of token".
2nd "value" variable were missing dollar signs.
function batchinsert($sql,$params){
try {
db->beginTransaction();
$stmt = db->prepare($sql);
foreach($params as $row)
{
// now loop through each inner array to match bound values
foreach($row as $column => $value)
{
$stmt->bindParam(":$column", $value);
}
$stmt->execute();
}
db->commit();
} catch(PDOExecption $e) {
$db->rollback();
}
}
Test:
$sql = "INSERT INTO `test`(`name`, `value`) VALUES (:name, :value)" ;
$data = array();
array_push($data, array('name'=>'Name1','value'=>'Value1'));
array_push($data, array('name'=>'Name2','value'=>'Value2'));
array_push($data, array('name'=>'Name3','value'=>'Value3'));
array_push($data, array('name'=>'Name4','value'=>'Value4'));
array_push($data, array('name'=>'Name5','value'=>'Value5'));
batchinsert($sql,$data);
Your code was actually ok, but had a problem in $stmt->bindParam(":$column", value); It should be $stmt->bindValue(":{$column}", $value); and it will work perfectly. This will assist others in future.
Full code:
foreach($params as $row)
{
// now loop through each inner array to match bound values
foreach($row as $column => $value)
{
$stmt->bindValue(":{$column}", $value); //EDIT
}
// Execute statement to add to transaction
$stmt->execute();
}
Move execute inside of the loop.
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
foreach($valuesToInsert as $insertRow)
{
$stmt->execute($insertRow);
}
If you experience any problems with this such recommended way, you have to ask a question, describing these certain problems.

Inserting multiple rows in a table using PHP

I am trying to insert multiple rows into MySQL DB using PHP and HTML from. I know basic PHP and searched many examples on different forums and created one script however it doesn't seem working. Can anybody help with this. Here is my script:
include_once 'include.php';
foreach($_POST['vsr'] as $row=>$vsr) {
$vsr=mysql_real_escape_string($vsr);
$ofice=mysql_real_escape_string($_POST['ofice'][$row]);
$date=mysql_real_escape_string($_POST['date'][$row]);
$type=mysql_real_escape_string($_POST['type'][$row]);
$qty=mysql_real_escape_string($_POST['qty'][$row]);
$uprice=mysql_real_escape_string($_POST['uprice'][$row]);
$tprice=mysql_real_escape_string($_POST['tprice'][$row]);
}
$sql .= "INSERT INTO maint_track (`vsr`, `ofice`, `date`, `type`, `qty`, `uprice`,
`tprice`) VALUES ('$vsr','$ofice','$date','$type','$qty','$uprice','$tprice')";
$result = mysql_query($sql, $con);
if (!$result) {
die('Error: ' . mysql_error());
} else {
echo "$row record added";
}
MySQL can insert multiple rows in a single query. I left your code as close as possible to the original. Keep in mind that if you have a lot of data, this could create a large query that could be larger than what MySQL will accept.
include_once 'include.php';
$parts = array();
foreach($_POST['vsr'] as $row=>$vsr) {
$vsr=mysql_real_escape_string($vsr);
$ofice=mysql_real_escape_string($_POST['ofice'][$row]);
$date=mysql_real_escape_string($_POST['date'][$row]);
$type=mysql_real_escape_string($_POST['type'][$row]);
$qty=mysql_real_escape_string($_POST['qty'][$row]);
$uprice=mysql_real_escape_string($_POST['uprice'][$row]);
$tprice=mysql_real_escape_string($_POST['tprice'][$row]);
$parts[] = "('$vsr','$ofice','$date','$type','$qty','$uprice','$tprice')";
}
$sql = "INSERT INTO maint_track (`vsr`, `ofice`, `date`, `type`, `qty`, `uprice`,
`tprice`) VALUES " . implode(', ', $parts);
$result = mysql_query($sql, $con);
Please try this code. Mysql query will not accept multiple insert using php. Since its is a for loop and the values are dynamically changing you can include the sql insert query inside the for each loop. It will insert each rows with the dynamic values. Please check the below code and let me know if you have any concerns
include_once 'include.php';
foreach($_POST['vsr'] as $row=>$vsr) {
$vsr=mysql_real_escape_string($vsr);
$ofice=mysql_real_escape_string($_POST['ofice'][$row]);
$date=mysql_real_escape_string($_POST['date'][$row]);
$type=mysql_real_escape_string($_POST['type'][$row]);
$qty=mysql_real_escape_string($_POST['qty'][$row]);
$uprice=mysql_real_escape_string($_POST['uprice'][$row]);
$tprice=mysql_real_escape_string($_POST['tprice'][$row]);
$sql = "INSERT INTO maint_track (`vsr`, `ofice`, `date`, `type`, `qty`, `uprice`,
`tprice`) VALUES ('$vsr','$ofice','$date','$type','$qty','$uprice','$tprice')";
$result = mysql_query($sql, $con);
if (!$result)
{
die('Error: ' . mysql_error());
}
else
{
echo "$row record added";
}
}
I would prefer a more modern approach that creates one prepared statement and binds parameters, then executes within a loop. This provides stable/secure insert queries and avoids making so many escaping calls.
Code:
// switch procedural connection to object-oriented syntax
$stmt = $con->prepare('INSERT INTO maint_track (`vsr`,`ofice`,`date`,`type`,`qty`,`uprice`,`tprice`)
VALUES (?,?,?,?,?,?,?)'); // use ?s as placeholders to declare where the values will be inserted into the query
$stmt->bind_param("sssssss", $vsr, $ofice, $date, $type, $qty, $uprice, $tprice); // assign the value types and variable names to be used when looping
foreach ($_POST['vsr'] as $rowIndex => $vsr) {
/*
If you want to conditionally abort/disqualify a row...
if (true) {
continue;
}
*/
$ofice = $_POST['ofice'][$rowIndex];
$date = $_POST['date'][$rowIndex];
$type = $_POST['type'][$rowIndex];
$qty = $_POST['qty'][$rowIndex];
$uprice = $_POST['uprice'][$rowIndex];
$tprice = $_POST['tprice'][$rowIndex];
echo "<div>Row# {$rowIndex} " . ($stmt->execute() ? 'added' : 'failed') . "</div>";
}
To deny the insertion of a row, use the conditional continue that is commented in my snippet -- of course, write your logic where true is (anywhere before the execute call inside the loop will work).
To adjust submitted values, overwrite the iterated variables (e.g. $vsr, $ofice, etc) before the execute call.
If you'd like to enjoy greater data type specificity, you can replace s (string) with i (integer) or d (double/float) as required.

Categories