Passing array in where condition in sql query using php - php

I am trying to pass a array in sql query.
Array contains coloumn names as index they are assigned to their respective values which i got using GET method.
for example iam trying to compile this code :
$a='email';
$b=array($a => $_GET['x']);
$sql="SELECT * FROM users WHERE $b";
echo $sql;
The output that i need is:
SELECT * FROM users WHERE email='/*value of $_GET['x']*/'
the output that i am getting is:
SELECT * FROM users where Array
can some one help me how to make it work.

You need to manipulate the $b array to make it into the string your after, at the moment it's just dumping the content in it's own format.
This version will do what your after...
$b=array($a => $_GET['x']);
$columns = [];
foreach ( $b as $name => $value ) {
$columns[] = "$name = '$value'";
}
$sql="SELECT * FROM users WHERE ".implode(" and ", $columns);
echo $sql.PHP_EOL;
I've made it use and as the condition linking multiple columns, you can change this depending on your requirement.
This version instead uses bind parameters, the place holder is inserted instead of the value in the query and then you will need to bind the $data array to the prepared statement (how depends in the API your using). This is safer and more flexible (and recommended)...
$b=array($a => $_GET['x']);
$columns = [];
$data = [];
foreach ( $b as $name => $value ) {
$columns[] = "$name = ?";
$data[] = $value;
}
$sql="SELECT * FROM users WHERE ".implode(" and ", $columns);
echo $sql.PHP_EOL;

Related

CodeIgniter 3 MySQL query randomly works intermittently

I made a function in a CI model that first queries for the table to get its fields(because these fields will change dynamically over time,so I can't hard code a list of field names),and then when it gets the results of the first query, and builds a fields name list,it queries the table again to get the values belonging to one row or record.It then stores the second query result in an array,which is passed back to the controller.Here is the complete function that performs these steps:
public function getAssetFeatures($as_id)
{
$data = array();
//this sql query gets the field names from the table I want to query.
$sql = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '".DATABASE."' AND TABLE_NAME = 'as_features';";
$query = $this->db->query($sql);
$count = 0;
foreach($query->result_array() as $k)
{
foreach($k as $kk=>$v)
{
if( $v != "as_features_id" &&
$v != "as_id" &&
$v != "cid" &&
$v != "lot_size" )
{
$features_array[$count] = $v;
$count++;
}
}
}
$features_string = implode(",",$features_array);
//I got the field names, put them into an array, then concatenated them into a string, which I will use for the fields in the next query:
$sql = "SELECT $features_string FROM as_features WHERE as_id='$as_id'";
$query = $this->db->query($sql);
//mandatory rooms/features:
foreach($query->result() as $row)
{
foreach($row as $k=>$v)
{
$data["$k"] = $v; //build an associative array with the values of each field for the one row I am querying
}
}
return $data; // return the associative array.
}
At first I thought something was broken in my table or view,but as I kept repeating the same call to the model function by refreshing the page and entering the exact same values,I noticed that sometimes the code worked,and I wouldn't get the errors "undefined index".
So I outputted the results of the array with this code:
echo "<pre>";
print_r($asset['features']);
echo "</pre>";
...and the expected output, which only performs successfully sometimes, but not all the time, for the exact same operation using the exact same parameters, looks like this:
Array
(
[kitchen] => 1
[liv_area] => 0
[dining] => 1
[family] => 0
[bed] => 0
[bath] => 1
[half_bath] => 0
[parking] => 0
[car_storage] => 0
[pool] => 0
[miscellaneous] => 0
)
When the query returns a result set and then a populated array,my form works and looks normal.but,most of the time the query fails,and I get what looks like this:
The issue is with the following snippet of code:
foreach($query->result() as $row)
{
foreach($row as $k=>$v)
{
$data["$k"] = $v; //build an associative array with the values of each field for the one row I am querying
}
}
The way it works is that for every result which is returned it will overwrite $data with the relevant keys. However, because the $query->result() will return the row you want, then return false, the array essentially ends up being:
$data[] = false; i.e., set the whole array to false/empty.
If you change the loop to be, the code inside the loop won't be executed for the false value of $query->result():
while ($row = $query->result())
{
// your code
}
It's worth noting that if you're intending to return more that one row from this, it won't work as it will just overwrite the existing values.
Ok, the problem was my code, not the query. I was passing an encrypted as_id, but neglected to unencrypt it before constructing the select query. That's why it would work sometimes, and not others. For some reason MySQL allowed the encrypted as_id to match existing as_id of INT type. After performing the decrypt, the query results became predictable. This is something I wouldn't expect SO members to have divined. Thanks.
public function getAssetFeatures($as_id)
{
$as_id = $this->utilityclass->decryption9($as_id); // <- I had this commented out. In fact, I removed the line from my example code in the original post, because I didn't think it was important to the question. Not only was it important, it was the problem!
$data = array();
$sql = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '".DATABASE."' AND TABLE_NAME = 'as_features';";
$query = $this->db->query($sql);

How to remove item on an array on php using mysql database data

I want to do something like this
----sql output----
name TEXT
b
c
$arr = ["a","b","c","d"];
foreach($arr as $key=>$val){
$query = "select count(*) from mydata where name = $val";
$count = xxxx($query);
if($count)unset($arr[$key]);
}
And $arr will be
a,d
Any simple way to do it but not checking every single element?
---edited---
I think I solve my problem myself...getting some inspired from mrlore that using having.
$arr = ["a","b","c","d"]; /* make the string inside arr safe for query */
$val = array_map(function($val){return "'$val'";},$arr);
$q = "select name from mydata where name in (" . implode(',',$val) .")";
$all = xxxxx($q);
$arr = array_diff($arr,$all);
This took me 0.8 second. Using my old way take 46 second and RST way takes 2 seconds.
---edited----
I have over 200k rows of data in my database, so I want a better way to optimize it.
--re MrLore--
ps : I don't know how to use stackoverflow to posting comments..so I just edit my post.
I have tried it on my mysql workbench but it does not seem to work for me.
select name from mydata
where name in("a","b","c","d")
having count(name) = 0
-- returns nothing
select name from mydata
where name in("a","b","c","d")
having count(name) > 0
$arr = ["a","b","c","d"];
$query = "select DISTINCT name from mydata";
$results = <result of query>;
foreach ($results as $result){
if(($key = array_search($result, $arr)) !== false) {
unset($arr[$key]);
}
}
Or the other way around
foreach ($arr as $key=>$value){
if( in_array( $value, $results) ) {
unset($arr[$key]);
}
}
By querying DISTINCT the database only returns unique values. You can then compare them with the array you have and remove them.

PHP form sending multiple inputs as SQL queries

I'm trying to create a PHP script that takes based on which input fields are filled in out of the total, uses those fields as SQL parameter to create a SQL query. But if none of the fields are filled out, then query would just retrieve all data.
Example: if fields "Name" and "City" are entered, then the query will have to concatenate "AND name = X_INPUT AND city = Y_INPUT" at the end.
I tried to instantiate $POST variables for the sake of testing but returns nothing. I'm not even sure if this is the best way to tackle the problem but any help would be greatly appreciated!
$_POST['name']="Linda";
$_POST['city']="";
$query = "select * from customers where gender = 'F'";
if (empty($_POST)) {
$query = "select * from customers where gender ='F'";
}
else{
foreach($_POST as $key => $v) {
if (!empty($_POST[$key])) {
$cond = " and ".$key."='".$v."'";
$query = $query.$cond;
The code:
$query = $query.$cond;
every appends unnecessary query to the SQL. Get all your conditions in an array and simple concatenate them as a string. Everything should work this way.
$conditions = array();
foreach($POST as $key => $v) {
if (!empty($_POST[$key])) {
$conditions = " $key = '$v'";
}
}
if (! empty($conditions)) {
$sql .= implode(' AND ', $conditions);
}
You have a typo in your foreach loop, Use this
$_POST
instead of
$POST

how to pass json array to select query

I have json array as below
$q=[{"con0":0},{"con1":1},{"con2":2}]
I want to pass this array to select query where query is as follows
$query="select * from table_name where con0='0' and con1='1' and con2='2'";
Shall we use json array to create this query?
The two tricks are to turn the json into a php array via json_decode and then use reset() and key() functions to get the column and condition. Here is the live example:
http://ideone.com/wp1kb1 you can read more about key http://php.net/key and reset http://php.net/reset
<?php
$q='[{"con0":0},{"con1":1},{"con2":2}]';
$ar = json_decode($q, true);
$where = array();
foreach ($ar as $condition) {
$value = reset($condition);
$column = key($condition);
$where[] = " `$column` = " . (int) $value;
}
$whereString = implode(' AND', $where);
$query="select * from table_name where $whereString";
echo "\n $query \n";
Use json_decode to make this an object/array and then use a loop to make a string for that and append to the sql query.
Loop the JSON decoded data inside a foreach, then grab the key-value pair , store them in an array and after the end of the loop, do an implode() on the array with AND and now pass the string to your query as shown.
$json='[{"con0":0},{"con1":1},{"con2":2}]';
$qstr=array();
foreach(json_decode($json,true) as $k=>$arr)
{
$qstr[]="`".key($arr)."`"." = ".$arr[key($arr)];
}
$qstr = implode(' AND ',$qstr); //looks like `con0` = 0 AND `con1` = 1 AND `con2` = 2
$query="select * from table_name where ".$qstr;

php & mysql - loop through columns of a single row and passing values into array

I have a mysql table with columns id, f1, f2, f3, ..., f20 where id is productID and f1,...f20 are product features. Depending on each product, some might have all, none or only some columns filled.
Each column holds a delimited string like a#b#c#d where a,b,c,d are values in different languages (a=english, b=french etc)
I need to select a row by it's id, explode each column's value (f1,f2...) with '#' in order to get the language part I need and then pass the values to an array in order to use in my product spec page.
How do I loop through the fetched row (i'm using $row = my_fetch_array) and put the exploded value into a one dimension array like $specs=('green', 'M', '100', 'kids'...) etc?
PS:I know, is complicated but I cant come up with a better idea right now.
Try this:
$result = mysql_query("...");
while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
$arr = array();
foreach ($row as $k=>$v)
{
$features = explode("#", $v);
$value = $features[1]; // get the specific language feature
$arr[] = $value;
}
$specs = join(", " , $arr);
}
Not sure this is the best way togo but you could define an array with your langs, then access the result by lang
<?php
$langs=array('eng'=>0,'fr'=>1,'ger'=>2,'geek'=>3);
while ($row=mysql_fetch_assoc($result)) {
$specs=explode('#',$row['f1']);
$other=explode('#',$row['f2']);
...
}
//Get lang from cookie that you could set elsewhere
$lang=(isset($_COOKIE['lang']))?$_COOKIE['lang']:'eng';
echo $specs[$langs[$lang]];
?>
My solution for how I understand you question:
// Make a MySQL Connection
$sQuery = "SELECT f1,f2,... FROM table WHERE id = ...";
$oResult = mysql_query($sQuery) or die(mysql_error());
//Fetch assoc to use the column names.
$aRow = mysql_fetch_assoc($oResult);
//Prepare the product properties array
$aProductProperties = array("English"=>array(),"French"=>array(),"Dutch"=>array());
//Loop over all the columns in the row
foreach($aRow as $sColName=>$sColVal){
//Explde the column value
$aExplodedCol = explode("#",$sColVal);
//The code below could be nicer when turned into a looped that looped over every language,
//But that would make the code less readable
$aProductProperties['English'][$sColName] = $aExplodedCol[0];
$aProductProperties['French'][$sColName] = $aExplodedCol[1];
$aProductProperties['Dutch'][$sColName] = $aExplodedCol[2];
}
//Done, you should now have an array with all the product properties in every language

Categories