arraymap vs foreach loop when creating a comma delimited string - php

I'm creating a comma delimited string for an SQL query. I would like to know what is better arraymap or a foreach loop. Here are my two examples:
$group_ids = "";
foreach ($group_array as $group_id) {
$group_ids .= $group_id . ",";
}
$group_ids = rtrim($group_ids, ',');
vs
$group_ids = "";
array_map(function ($group_id) use ($group_ids) {
$group_ids .= $group_id . ",";
return;
}, $group_array);
$group_ids = rtrim($group_ids, ',');
Or is there a better way? Or is there literally not much difference?

$array = array('lastname', 'email', 'phone');
$comma_separated = implode(",", $array);
from
http://php.net/manual/en/function.implode.php
would be more efficient

You can also use implode(',',$array_of_ids). Just make sure you trim your values before using the implode.
$ids = ['foo','bar','boo'];
$ids = array_map('trim',$ids);
$ids_list = implode(',',$ids);
echo $ids_list; # foo,bar,boo

Related

How to generate a WHERE clause from an array with multiple AND-conditions

I have an HTML-table, where various selections can be made. The selected variables that contain the respective values, build the array $data[]. Now, with this array I would like to make an SQL request where all selected criteria should be met. This means, that I need the following request:
SELECT * FROM fruitgroups
WHERE $selection[1] = $value[1]
AND $selection[2] = $value[2]
AND $selection[3] = $value[3]
etc ...
Can anybody please help me with the loop that generates exactly the string:
...
$selection[1] = $value[1]
AND $selection[2] = $value[2]
AND $selection[3] = $value[3]
... etc ...
...that I need for the request?
Thank you in advance!
You can make a SQL request like this:
$selection = array("one", "two", "three");
$value = array("Tone", "Ttwo", "Tthree");
$concat = array();
foreach($selection as $key => $var){
$new = $selection[$key] . " = " . $value[$key];
array_push($concat, $new);
}
$concat = implode(" AND ", $concat);
$request = 'SELECT * FROM fruitgroups WHERE ' . $concat . ';';
echo $request;
Run example
Similar to the answer above, but keep it simple and don't forget the single quotes around the values:
$clauses = [];
foreach ($values as $i => $value) {
$conditions[] = "{$selection[$i]} = '$value'";
}
$query = "SELECT * FROM fruitgroups WHERE " . implode(' AND ', $conditions);
Even better, use an ORM like Eloquent:
$conditions = [];
foreach ($values as $i => $value) {
$conditions[$i] = $value;
}
$result = App\FruitGroups::where($conditions)->get();
I'm assuming you are sanitizing your inputs first, of course.

Concatenation of string with a specific array elements

the given code below insert data from an array to the mysql table.as its not the full code but what i want to know is available in this code. my question is that there is a field in table named "image_url" but the data in that field only have image name and i want to append http://www.xxxxxx.com at the start of every image name and the replace it with the image name in the field but i dont know how to do that plz help me out
thanks in advance
function putTest($t) {
//$c = connect();
foreach ($t as $k => $v) {
$query = "INSERT INTO test (".implode(',',array_keys($v)).") VALUES ('".implode("','",$v)."')";
//echo "<pre>";
// echo $query;
$r = mysql_query($query);
}
//mysql_close($c);
}
This snippet should do what you want:
if (isset($v['image_url'])) {
$v['image_url'] = 'http://www.xxxxxx.com/' . $v['image_url'];
}
You can concatenate strings with the dot "."!
At first... Is your application protected against SQL injection? If not you should build two methods/functions like this using mysql_real_escape_string():
function sqlSafeKey( $key){
return '`' . mysql_real_escape_string( $key) . `'`;
}
function sqlSafeValue( $value){
return "'" . mysql_real_escape_string( $value) . "'";
}
And than use array_map() to escape your values like this:
$keys = array_map( 'sqlSafeKey', array_keys( $v));
$values = array_map( 'sqlSafeValue', $v);
About your question... The matzino's answer is correct and whole loop should look like this:
function putTest($t) {
//$c = connect();
foreach ($t as $k => $v) {
$v['image_url'] = 'http://www.xxxxxx.com/' . $v['image_url'];
$keys = array_map( 'sqlSafeKey', array_keys( $v));
$values = array_map( 'sqlSafeValue', $v);
$query = "INSERT INTO test (".implode(',', $keys).
") VALUES ('".implode("','",$values)."')";
//echo "<pre>";
// echo $query;
$r = mysql_query($query);
}
//mysql_close($c);
}

php implode (101) with quotes

Imploding a simple array
would look like this
$array = array('lastname', 'email', 'phone');
$comma_separated = implode(",", $array);
and that would return this
lastname,email,phone
great, so i might do this instead
$array = array('lastname', 'email', 'phone');
$comma_separated = implode("','", $array);
$comma_separated = "'".$comma_separated."'";
and now i have what I want a nice pretty csv string
'lastname','email','phone'
is there a better way to do this, it feels to me like there should be an optional parameter for implode am I missing something ?
$array = array('lastname', 'email', 'phone');
echo "'" . implode("','", $array) . "'";
$ids = sprintf("'%s'", implode("','", $ids ) );
You could use array_map():
function add_quotes($str) {
return sprintf("'%s'", $str);
}
$csv = implode(',', array_map('add_quotes', $array));
DEMO
Also note that there is fputcsv if you want to write to a file.
No, the way that you're doing it is just fine. implode() only takes 1-2 parameters (if you just supply an array, it joins the pieces by an empty string).
Don't know if it's quicker, but, you could save a line of code with your method:
From
$array = array('lastname', 'email', 'phone');
$comma_separated = implode("','", $array);
$comma_separated = "'".$comma_separated."'";
To:
$array = array('lastname', 'email', 'phone');
$comma_separated = "'".implode("','", $array)."'";
If you want to use loops you can also do:
$array = array('lastname', 'email', 'phone');
foreach($array as &$value){
$value = "'$value'";
}
$comma_separated = implode(",", $array);
Demo: http://codepad.org/O2kB4fRo
$id = array(2222,3333,4444,5555,6666);
$ids = "'".implode("','",$id)."'";
Or
$ids = sprintf("'%s'", implode("','", $id ) );
Alternatively you can create such a function:
function implode_with_quotes(array $data)
{
return sprintf("'%s'", implode("', '", $data));
}
try this code :
$data = 'ABC,DEF,GHI';
$str = "'".str_replace(',',"','",$data)."'";
echo $str;
If you want to avoid the fopen/fputcsv sub-systems here's a snippet that builds an escaped CSV string from an associative array....
$output = '';
foreach ($list as $row) {
$output .= '"' . implode('", "', array_values($row)) . '"' . "\r\n";
}
Or from a list of objects...
foreach ($list as $obj) {
$output .= '"' . implode('", "', array_values((array) $obj)) . '"' . "\r\n";
}
Then you can output the string as desired.
Another possible option, depending on what you need the array for:
$array = array('lastname', 'email', 'phone');
echo json_encode($array);
This will put '[' and ']' around the string, which you may or may not want.
Don't forget to escape your data!
If you want to put data in a CSV file without fputcsv function or put it in a SQL query use this code:
$comma_separated = "'" . implode("','", array_map('addslashes', $array)) . "'";
This code avoids SQL injection or data fragmentation when input array contains single quotation or backslash characters.
Another solution is achieved using implode + preg_replace as follows:
$a = ['A', 'B', 'C'];
implode(',', preg_replace('/^(.*)$/', '"$1"', $a)); // "A","B","C"
$b = [];
implode(',', preg_replace('/^(.*)$/', '"$1"', $b)); // empty string
As you can see this also saves you from checking if the array is empty.
you can do it this way also
<?php
$csv= '\'' . join(array('lastname', 'email', 'phone'),'\',').'\'';
echo $csv;
?>
I think this is what you are trying to do
$array = array('lastname', 'email', 'phone');
echo "'" . implode("','", explode(',', $array)) . "'";

PHP foreach loop

I have the array example below that I am using to dynamically create an SQL query based on the options ticked in a form. The code below tests whether there is a value, if so, append it to the array:
if ($lookchild) { $val[]='lookchild'; }
if ($mentalcap) { $val[]='mentalcap'; }
if ($mentalheal) { $val[]='mentalheal'; }
if ($olderpeople) { $val[]='olderpeople'; }
if ($palcare) { $val[]='palcare'; }
I am then looping through the array and adding the rest of the SQL statement:
foreach ($val as $r){
echo $r.'=1 AND ';
}
This produces:
olderpeople=1 AND palcare=1 AND lookchild=1 AND
When the loop reaches the last entry, I don't want it to append the AND to it as the SQL statement needs to close after that point.
How I want it to complete:
olderpeople=1 AND palcare=1 AND lookchild=1
Implode
In these situations you can use implode
It 'glues' an array together.
implode ( string $glue , array
$pieces )
Example:
echo implode('=1 AND ', $val);
echo '=1';
A common trick is to use 'WHERE 1=1' then you can append ' AND foo = bar' without a syntax error.
WHERE 1=1 AND olderpeople=1 AND palcare=1 AND lookchild=1
This is what implode() is for:
$result = array();
foreach ($val as $r){
$result[] = "$r=1";
}
$result = implode($result, ' AND ');
Live Example
Just don't print the AND for the last value of the foreach loop. Here is the code to use:
foreach ($val as $r){
echo $r.'=1';
if (next($val)) {
echo ' AND ';
}
}
use the implode function
$sql = implode("=1 AND ", $array)."=1";
and you wont have to use a for loop :)
Instead on assigning palcare to $val[], assign $val[] = "palcare = 1" etc. Them
implode(" AND ", $val);
Try this :
$isFirst = true;
foreach ($val as $r){
if(!$isFirst){
echo ' AND ';
}else{
$isFirst = false;
}
echo $r.'=1';
}
I would remove the last 4 characters of the string with:
$r = '';
foreach ($val as $r){
$r.'=1 AND ';
}
$r = substr($r, 0, -4);
echo $r;
Checkout http://ca3.php.net/manual/en/function.substr.php, quick and easy
If you have to do it with a foreach (and for some reason you cant use implode, which is a good suggestion) you will need a way to keep track of where you are.
I thought to add the "AND" before anything but the first item, instead of adding it after anything but the last item, something like this:
$sqlwhere = "";
foreach ($val as $r){
if($sqlwhere ==""){
$sqlwhere = $r;
}
else {
$sqlwhere .= " AND " . $sqlwhere;
}
}
echo $sqlwhere;
I used a varable instead of just echoing it out too, which I find useful in complicated sql statements anyway.
Use implode. But if for some reason you need to loop (such as you need to do more logic than just joining the strings), use a separator approach:
$seperator = '';
$result = '';
foreach ($array as $value) {
// .. Do stuff here
$result .= $seperator . $value;
$seperator = ' AND ';
}
The benefit is both brevity and flexibility without checking conditions all the time...
Since you are using an array, you can also use count to figure out how many are in the array and if you are on the last item, don't append the 'AND'.
$result = array();
$totalcount = count($val);
$currentCount = 0;
foreach ($val as $r){
$currentCount ++;
if ($currentCount != $totalcount){$result[] = "$r=1 AND ";}else{$result[] = "$r=1";}
}

PHP Implode Associative Array

So I'm trying to create a function that generates a SQL query string based on a multi dimensional array.
Example:
function createQueryString($arrayToSelect, $table, $conditionalArray) {
$queryStr = "SELECT ".implode(", ", $arrayToSelect)." FROM ".$table." WHERE ";
$queryStr = $queryStr.implode(" AND ",$conditionalArray); /*NEED HELP HERE*/
return $queryStr;
}
$columnsToSelect = array('ID','username');
$table = 'table';
$conditions = array('lastname'=>'doe','zipcode'=>'12345');
echo createQueryString($columnsToSelect, $table, $conditions); /*will result in incorrect SQL syntax*/
as you can see I need help with the 3rd line as it's currently printing
SELECT ID, username FROM table WHERE
lastname AND zipcode
but it should be printing
SELECT ID, username FROM table WHERE
lastname = 'doe' AND zipcode = '12345'
You're not actually imploding a multidimensional array. $conditions is an associative array.
Just use a foreach loop inside your function createQueryString(). Something like this should work, note it's untested.:
$terms = count($conditionalArray);
foreach ($conditionalArray as $field => $value)
{
$terms--;
$queryStr .= $field . ' = ' . $value;
if ($terms)
{
$queryStr .= ' AND ';
}
}
Note: To prevent SQL injection, the values should be escaped and/or quoted as appropriate/necessary for the DB employed. Don't just copy and paste; think!
function implodeItem(&$item, $key) // Note the &$item
{
$item = $key . "=" . $item;
}
[...]
$conditionals = array(
"foo" => "bar"
);
array_walk($conditionals, "implodeItem");
implode(' AND ', $conditionals);
Untested, but something like this should work. This way you can also check if $item is an array and use IN for those cases.
You will have to write another function to process the $conditionalArray, i.e. processing the $key => $value and handling the types, e.g. applying quotes if they're string.
Are you just dealing with = condition? What about LIKE, <, >?
Forgive me if its not too sexy !
$data = array('name'=>'xzy',
'zip'=>'3432',
'city'=>'NYK',
'state'=>'Alaska');
$x=preg_replace('/^(.*)$/e', ' "$1=\'". $data["$1"]."\'" ',array_flip($data));
$x=implode(' AND ' , $x);
So the output will be sth like :
name='xzy' AND zip='3432' AND city='NYK' AND state='Alaska'
I'd advise against automated conditionals creation.
Your case is too local, while there can be many other operators - LIKE, IN, BETWEEN, <, > etc.
Some logic including several ANDs and ORs.
The best way is manual way.
I am always doing such things this way
if (!empty($_GET['rooms'])) $w[]="rooms='".mesc($_GET['rooms'])."'";
if (!empty($_GET['space'])) $w[]="space='".mesc($_GET['space'])."'";
if (!empty($_GET['max_price'])) $w[]="price < '".mesc($_GET['max_price'])."'";
Though if you still want it with this simple array, just iterate it using
foreach ($conditions as $fieldname => $value)...
and then combine these variables in the way you need. you have 2 options: make another array of this with field='value' pairs and then implode it, or just concatenate, and substr trailing AND at the end.
I use a variation of this:
function implode_assoc($glue,$sep,$arr)
{
if (empty($glue)) {$glue='; ';}
if (empty($sep)) {$sep=' = ';}
if (is_array($arr))
{
foreach ($arr as $k=>$v)
{
$str .= $k.$sep.$v.$glue;
}
return $str;
} else {
return false;
}
};
It's rough but works.
Here is a working version:
//use: implode_assoc($v,"="," / ")
//changed: argument order, when passing to function, and in function
//output: $_FILES array ... name=order_btn.jpg / type=image/jpeg / tmp_name=G:\wamp\tmp\phpBDC9.tmp / error=0 / size=0 /
function implode_assoc($arr,$glue,$sep){
$str = '';
if (empty($glue)) {$glue='; ';}
if (empty($sep)) {$sep=' = ';}
if (is_array($arr))
{
foreach ($arr as $key=>$value)
{
$str .= $key.$glue.$value.$sep;
}
return $str;
} else {
return false;
}
}
I know this is for the case of a pdo mysql type.. but what i do is build pdo wrapper methods, and in this case i do this function that helps to build the string, since we work with keys, there is no possible way to mysql inject, since i know the keys i define / accept manually.
imagine this data:
$data=array(
"name"=>$_GET["name"],
"email"=>$_GET["email"]
);
you defined utils methods...
public static function serialize_type($obj,$mode){
$d2="";
if($mode=="insert"){
$d2.=" (".implode(",",array_keys($obj)).") ";
$d2.=" VALUES(";
foreach ($obj as $key=>$item){$d2.=":".$key.",";}
$d2=rtrim($d2,",").")";}
if($mode=="update"){
foreach ($obj as $key=>$item){$d2.=$key."=:".$key.",";}
}
return rtrim($d2,",");
}
then the query bind array builder ( i could use direct array reference but lets simplify):
public static function bind_build($array){
$query_array=$array;
foreach ($query_array as $key => $value) { $query_array[":".$key] = $query_array[$key]; unset($query_array[$key]); } //auto prepair array for PDO
return $query_array; }
then you execute...
$query ="insert into table_x ".self::serialize_type( $data, "insert" );
$me->statement = #$me->dbh->prepare( $query );
$me->result=$me->statement->execute( self::bind_build($data) );
You could also go for an update easy with...
$query ="update table_x set ".self::serialize_type( $data, "update" )." where id=:id";
$me->statement = #$me->dbh->prepare( $query );
$data["id"]="123"; //add the id
$me->result=$me->statement->execute( self::bind_build($data) );
But the most important part here is the serialize_type function
Try this
function GeraSQL($funcao, $tabela, $chave, $valor, $campos) {
$SQL = '';
if ($funcao == 'UPDATE') :
//Formata SQL UPDATE
$SQL = "UPDATE $tabela SET ";
foreach ($campos as $campo => $valor) :
$SQL .= "$campo = '$valor', ";
endforeach;
$SQL = substr($SQL, 0, -2);
$SQL .= " WHERE $chave = '$valor' ";
elseif ($funcao == 'INSERT') :
//Formata SQL INSERT
$SQL = "INSERT INTO $tabela ";
$SQL .= "(" . implode(", ", array_keys($campos) ) . ")";
$SQL .= " VALUES ('" . implode("', '", $campos) . "')";
endif;
return $SQL;
}
//Use
$data = array('NAME' => 'JOHN', 'EMAIL' => 'J#GMAIL.COM');
GeraSQL('INSERT', 'Customers', 'CustID', 1000, $data);

Categories