iteration problems with foreach loop - php

I'm trying to make a function that creates a sql statement to insert data into a database and this is a snippet. It works fine except for the last foreach loop. For some reason it won't iterate to the last element in the array it'll stay stuck on the second last one. The issue is that the first foreach loop is the same code and it works fine, but the second is giving me trouble.
*note:The if statements in the foreach loops are supposed to catch the last element in the array and make sure that a ',' isn't inserted. And this is where the problem is. If I take the if statement out of the second loop the loop will iterate to the last element but without the if block it places a comma at the end and creates a SQL syntax error.
output of the first loop
INSERT INTO gardyloo.users (joe,bob,joe#hotmail.com,8de,154927,2014-12-18,2014-12-18 7:02:11)
output of second loop without if
VALUES (:firstName,:lastName,:emailAddress,:password,:userid,:date_joined,:timestamp,)
output of second loop with if
VALUES (:firstName,:lastName,:emailAddress,:password,:userid,:date_joined)
foreach( $values as $a => $b ){
if(next($values) == null){
$sql .= $b."";
break;
}
$sql .= $b.",";
}
$sql .= ") ";
$sql .= "VALUES (";
foreach( $values as $a => $b ){
if(next($values) == null){
$sql .= ":".$a;
break;
}
$sql .= ":".$a.",";
}
$sql .= ")";
*Edit, this code seems to work fine:
$sql .= implode(', ', array_keys($values));
$sql .= ") ";
$sql .= "VALUES (:";
$sql .= implode(", :", array_keys($values));
$sql .= ")";

Instead of break you need to use continue; Break interrupts the loop, while continue only move to next iteration.
Try this:
foreach( $values as $a => $b ){
if($b == null){
continue;
}
$sql .= ":".$a.",";
}

Do something like this:
//Your data
$values = array(
'firstName' => 'Joe',
'lastName' => 'bob',
'emailAddress' => 'joe#hotmail.com',
'password' => '8de',
'userid' => 154927,
'date_joined' => '2014-12-18',
'timestamp' => '2014-12-18 7:02:11'
);
//Begins the sentence
$sql = 'INSERT INTO gardyloo.users(';
/**
* Begins example code.
* - array_keys shows the key as a value
* example: $values[0] = firstName
*/
foreach(array_keys($values) as $k => $v)
{
//when the array arrives at the end, doesn't show ','
if($k != count($values)-1)
$sql .= $v.",";
else
$sql .= $v;
}
$sql .= ") ";
$sql .= "VALUES (";
$k = 0;//the new count initialized
foreach($values as $v)
{
//when the array arrives at the end, doesn't show ','
if($k != count($values)-1)
$sql .= $v.",";
else
$sql .= $v;
//increments the counter
$k++;
}
$sql .= ");";
Notes:
Separate the code in functions since both foreachs are very similar.
You can play with the foreach values to return the value that you want.
Ask me if you have more questions about it.

I'll do it otherwise. Instead of concat a string $sql create 2 variables, $columns and $values, both are arrays. And you don't need a loop to do this.
So here is how i would do it :
$columns = array_keys($values);
$sql = "INSERT INTO table (". implode(" ,", $columns) . ") VALUES (". implode(" ,", $values);
Here you don't need to test if it's the last element of the array to make a break;
Hope it helps ;)

Related

What is the purpose of strlen($query)-2;

I got this code from google and it fulfills my requirement, but I don't understand the meaning of this line:
substr($query,0,strlen($query)-2)
Could somebody explain it to me?
<?php
function insert($tablename, $parameter_order, $values)
{
$query = "insert into $tablename (";
foreach($parameter_order as $po)
{
$query .= $po.', ';
}
$query = substr($query,0,strlen($query)-2).') values (';
foreach($values as $v)
{
$query .= "'$v', ";
}
$query = substr($query,0,strlen($query)-2).');';
return $this->makeQuery($query);
}
?>
This is what those functions do exactly:
substr() is used to generate a sub-string of specified length from another string.
strlen() will return the length of the provided string.
Code substr($query,0,strlen($query)-2) removes comma and space from foreach Loop.
The line removes the last comma and space from $query. These characters have been added in the foreach loop to glue together the elements of $parameter_order.
Note that this standard task is usually done better with the implode() function:
$query = "insert into $tablename (" . implode (', ', $parameter_order) . ' ) values (';

More elegant way in PHP to generate a query from array elements

When I need to loop over something while generating a query from each element, I would use something like
$queryStr = "INSERT INTO tableName (x,y) VALUES ";
for ($i = 0 ; $i < $len ; $i++)
{
$queryStr .= "( ".$thing[$i]['x'].", ".$thing[$i]['b']."), ";
}
//extra code to remove the last comma from string
Would there be an alternative?
I don't mind performance too much (knowing the length of the array is not too big), just something that looks nicer.
Using a prepared statement:
$sql = 'INSERT INTO tableName (x, y) VALUES (:x, :y)';
$sth = $dbh->prepare($sql);
for ($i = 0 ; $i < $len ; $i++)
{
$sth->execute(array(
':x' => $thing[$i]['x'],
':y' => $thing[$i]['b']));
}
More examples: http://www.php.net/manual/en/pdo.prepare.php
A slight improvement to get rid of last part (removing latest comma). You can first create an array of values, then use implode function like:
$queryStr = "INSERT INTO tableName (x,y) VALUES ";
for ($i = 0 ; $i < $len ; $i++)
{
$values[] = "( ".$thing[$i]['x'].", ".$thing[$i]['b'].")";
}
$queryStr .= implode(',', $values);
I like using array_walk and implode for things like this:
$values = array(
array(1, 2, 3),
array(4, 5, 6),
. . .
);
// an array to hold the values to insert
$query = array();
// walk the values and build the query array
array_walk($values, function($v) use(&$query) {
$query[] = "(" . implode(", ", $v) . ")";
});
// dump the output
echo implode(", ", $query);
The result looks like this:
(1, 2, 3), (4, 5, 6), ...
Maybe not much cleaner, but at least it gets rid of the for loop :-)
You could use implode() with array_map():
implode(', ', array_map(function($v) { return '(' . $v['x'] . ', ' . $v['b'] . ')'; }, $things));
Demo
$strCols = '`'.implode('`, `',array_keys($arrValues)).'`'; //Sets the array keys passed in $arrValues up as column names
if ($bolEscape){ //Checks if $bolEscape is true
$arrValues = $this->escape($arrValues); //Calls the escape function
$strValues = '"'.implode('","',array_values($arrValues)).'"'; //Sets the array values passed in $arrValues up as data for the columns
}else{
$strValues = '"'.implode('","',array_values($arrValues)).'"'; //Sets the array values passed in $arrValues up as data for the columns WITHOUT escaping
}
//Creates the SQL statement for the query
$strSQL = 'INSERT INTO `' . $strTable . '` (' . $strCols . ') VALUES (' . $strValues . ')';
Thats part of the database class I have written... I pass in the arrValues ('ColumnName'=>'Value')

PHP -> PDO Update Function using Foreach array merge

The following code is supposed to check for the column names of a table. Then check to see if a corresponding variable has been $_POST and if it has add it to the $SQL. I believe there is a problem with the array that contains a series of arrays but I don't know how to dix it.
$where = $_POST['where'];
$is = $_POST['is'];
$table = $_POST['table'];
$sql = "UPDATE $table SET";
$array = array();
$columnnames = columnnames('blog');
foreach ($columnnames as $columnname){
if($_POST[$columnname]){
$sql .= " $columnname = :$columnname,";
$array .= array(':$columnname' => $_POST[$columnname],);
}
}
$sql = rtrim($sql,',');
$array = rtrim($array,',');
$sql .= " WHERE $where = '$is'";
$q = $rikdb->prepare($sql);
$q->execute($array);
For the sake of comprehension please except that $columnnames = columnnames('blog'); works as it does.
Change this:
$array .= array(':$columnname' => $_POST[$columnname],);
to this:
$array[':$columnname'] = $_POST[$columnname];
and after that use rtrim only on $sql.
the problem is here $array .= array(':$columnname' => $_POST[$columnname],);
you have a , part of the value which is not literal. change it to be like
$array .= array(':$columnname' => $_POST[$columnname] . ",");
You can also add your column names and values to an array and implode(",", $array) so you don't have to use rtrim
Instead of using
$array .= array(':$columnname' => $_POST[$columnname],);
and applying rtrim on results, I'd suggest the easier and failsafe method:
$array[':$columnname'] = $_POST[$columnname];

How to 'really' detect integers from DB?

I'm trying to save some code with the following. I've an object with variables named the same as table rows so I could create an insert like this one:
$query = "INSERT INTO table ";
$columns = '(';
$values = 'VALUES (';
foreach ($this as $var => $value){
if ($value){
$columns .= $var.', ';
if (!is_int($value))
$value = '\''.$value.'\'';
$values .= $value.', ';
}
}
$columns .= ')';
$values .= ')';
$columns = str_replace (', )', ')', $columns);
$values = str_replace (', )', ')', $values);
$query .= $columns." ".$values;
But every single variable is detected as string and that's not true in all fields as you may imagine.
Does anyone have a solution?
Here's how I would write it:
<?php
$canonical_columns = array_flip(array("column1", "column2", "column3"));
$columns = array_keys(array_intersect_key($canonical_columns, (array) $this));
$params = join(",", array_fill(0, count($columns), "?"));
$columns = join(",", $columns);
$query = "INSERT INTO table ($columns) VALUES ($params)";
$stmt = $pdo->prepare($query);
$stmt->execute(array_values($this));
Stop concatenating fragments of strings to form SQL.
Use PDO, and use parameters for values.
Allowlist column names by comparing inputs to known, valid column names.
It appears as if you numbers are in fact strings. Try to use is_numeric() instead of is_int().
If this ain't enough you can cast the string to an integer and then check for != 0.
You may insert numbers in quotes too, as strings. This will not create an error.

Foreach loop with multiple arrays [duplicate]

This question already has answers here:
Two arrays in foreach loop
(24 answers)
Closed last month.
This is what I want:
foreach($_POST['something'] as $something){
foreach($_POST['example'] as $example){
$query = mysql_query("INSERT INTO table (row, row2) VALUES ('{$something}','{$example}')");
}
}
$_POST['something'] and $_POST['example'] are arrays from an input with
name="something[]" and name="example[]".
The problem:
In this way I will send the data twice to database. So I need a solution where I can loop trough 2 arrays without seding the data twice.
EDIT
The two array will always have the same size
In the mysql_query I will have other elements not just row, row2, and those will be static without any array.
Do you mean something like:
foreach($_POST['something'] as $key => $something) {
$example = $_POST['example'][$key];
$query = mysql_query("INSERT INTO table (row, row2) VALUES ('{$something}','{$example}')");
}
SOLUTION FOR MULTIPLE Arrays
TRY -
1)
<?php
$ZZ = array('a', 'b', 'c', 'd');
$KK = array('1', '2', '3', '4');
foreach($ZZ as $index => $value) {
echo $ZZ[$index].$KK[$index];
echo "<br/>";
}
?>
or 2)
<?php
$ZZ = array('a', 'b', 'c', 'd');
$KK = array('1', '2', '3', '4');
for ($index = 0 ; $index < count($ZZ); $index ++) {
echo $ZZ[$index] . $KK[$index];
echo "<br/>";
}
?>
Your solution does not seem to send the data twice. Unless if records with the same values appear as a result of issuing your queries. This might mean that you should process your data before constructing your queries.
One solution could be:
$sql = array();
foreach($_POST['something'] as $something){
foreach($_POST['example'] as $example){
$sql[] = "INSERT INTO table (row, row2) VALUES ('{$something}','{$example}')";
}
}
foreach($sql as $query){
mysql_query($query);
}
I think the best way would be as a single loop to build a query. This should work even if your arrays are not the same length:
$size1 = count($_POST['something']);
$size2 = count($_POST['example']);
if( $size1 >= $size2 ) {
$size = $size1;
} else {
$size = $size2;
}
$sql = "INSERT INTO table (row, row2) VALUES";
$values = array();
for( $i=0; $i<$size; $i++ ) {
$values[] = "('" . mysql_real_escape_string($_POST['something'][$i]) . "','" . mysql_real_escape_string($_POST['example'][$i]) . "')";
}
$sql .= implode(",", $values);
mysql_query($sql);
Also more secure because it escapes your input. This would also be even easier using placeholders with PDO.
$cnt = count($_POST['something']);
$cnt2 = count($_POST['example']);
if ($cnt > 0 && $cnt == $cnt2) {
$insertArr = array();
for ($i=0; $i<$cnt; $i++) {
$insertArr[] = "('" . mysql_real_escape_string($_POST['something'][$i]) . "', '" . mysql_real_escape_string($_POST['example'][$i]) . "')";
}
$query = "INSERT INTO table (column, column2) VALUES " . implode(", ", $insertArr);
mysql_query($query) or trigger_error("Insert failed: " . mysql_error());
}
Here is another method. This one uses extended inserts, so should be more efficient and quicker, and utilizes mysql_real_escape_string for security reasons. The count check is to just make sure that both fields have the same count, if not then I take this is a mishap. If they are allowed to have a different number of fields, you can simply use the isset() function to check to make sure they contain a value.
EDIT
This is assuming of course, that you do not want 'something' to iterate over all the 'example' values and be assigned to each one. If you want that well it is a bit of a change up.
Added an insert array test, if there are no elements no need to update. Thanks Gumbo for that.
Although you already selected an answer, don't forget this piece of script may fail if the POST values are not arrays. You can overcome this with a small piece of code:
$something = is_array($_POST['something']) ? $_POST['something'] : array();
$example = is_array($_POST['example']) ? $_POST['example'] : array();
/* Get all the keys from both arrays
* If they don't share the keys, none will be lost
*/
$keys = array_merge(array_keys($something),array_keys($example));
$keys = array_unique();
if (count($keys)) {
$sql = 'INSERT INTO table (row, row2) VALUES ';
$values = array();
foreach ($keys as $key) {
// Single quotes for PHP, we are not expanding variables
// If the element cannot be converted into a string, don't show the error on screen
$values[] = '("' . #mysql_real_escape_string($something[$key]) . '","' . #mysql_real_escape_string($example[$key]) . '")';
}
$sql .= implode(',', $values);
mysql_query($sql);
}
Foreach loop with multiple arrays:
foreach($_POST['quantity'] as $key=>$quantity)
{
$product_no=$_POST['product_id'][$key];
echo $product_no;
echo $quantity;
}
Yours example dont work in me.
I made like this :
if($_POST[add_all])
{
$n=0;
foreach($_POST['pieces'] as $checked)
{
if ($checked!=0)
{
$box=$_POST['box'];
echo $box[$n]." ".$checked . ' <br>';
$n++;
}
}
<input type="submit" id="coin" name="add_all" value="..Test.."><BR>
<select name="pieces[]">
<?php for ($x=0;$x<=20;$x++){ echo "<option>$x</option>";} ?>
<input type="checkbox" name="box[]" value="<?php echo"$row_produkt";?>">

Categories