PHP/SQL - Combining AND & OR in a foreach() - php

I'm sending json to the server like this:
{"data":{"tags":[{"tag":"Paris"},{"tag":"New York"},{"tag":"London"}]},"terms":{"term":"index"}}
... and with foreach() I'm appending the provided tags to the query:
$query = "SELECT name FROM accounts
WHERE name = '".$term."'";
foreach($tags as $t=>$tag){
$tag = $tag['tag'];
$query.=" AND city = '".$tag."'";
}
... to replicate this:
SELECT name FROM accounts
WHERE name=$term
AND city=$tag
AND city=$tag
AND city=$tag;
But how should the foreach() look like if I want to provide replicate this:
SELECT name FROM accounts
WHERE name=$term
AND (city=$tag OR city=$tag OR city=$tag);

It's better way to use IN clause in query and implode function to form it:
$tags_list = array();
foreach($tags as $t=>$tag){
$tags_list[] = $tag['tag'];
}
$query = "SELECT name FROM accounts
WHERE name = '".$term."'";
if ($tags_list) {
$query .= " AND city IN ('".implode("', '", $tags_list)."')";
}

The Problem with this is that in your sql query the column name couldn't have 2 tags at the same time. for example
WHERE name = true AND name = false
wouldn't make any sense.
so u should use something like this
WHERE name in ($tag, $term, $tag2);
and therefore u should adapt your php code as well
$first = true;
$query = "SELECT name FROM accounts
WHERE name2 = '$term' and name in ("
foreach($tags as $t=>$tag){
$tag = $tag['tag'];
if($first == false) {
$query.=",";
}
$query.="'".$tag."'";
$first = false;
}
$query.=")";

Related

php mysql search row with multiple arrays in cells

ok, so stay with me here ...
i have a site with a table of about 80,000 rows; i am trying to search this table with one MySQL query. The problem is that each of the fields in the row i'm searching has / might have an array (ex: year = 2017,2016,2015, etc), and some of them may not have anything at all. i have tried doing a loop through to and build my "WHERE" clause as i pull the results, but that isn't working either.
any thoughts? any and all help will be greatly appreciated.
CODE:
INSERT INTO the table - this is one of the 13 different rows
if(!empty($_POST['pd_year']) && is_array($_POST['pd_year'])) {
$pd_year = implode(",", $_POST['pd_year']);
$insert_year = mysqli_query($con, "UPDATE prod_desigs_search_test SET pds_year = '$pd_year' WHERE s_id = '$search'");
} elseif(empty($_POST['pd_year'])) {
$insert_year = mysqli_query($con, "UPDATE prod_desigs_search_test SET pds_year = ' ' WHERE s_id = '$search'");
}
SELECT THE design and check if it is an array or not:
$get_search = mysqli_query($con, "SELECT * FROM prod_desigs_search_test WHERE s_id = '$s_id'");
while($new_search = mysqli_fetch_array($get_search)) {
$pd_year_ex = $new_search['pds_year'];
if(!empty($pd_year_ex) && is_array($pd_year_ex)) {
$pd_year = explode(",", $pd_year_ex, 0);
$year = $pd_year[0];
} elseif(!empty($pd_year_ex) && !is_array($pd_year_ex)) {
$year = $pd_year_ex;
}
$search = mysqli_query($con, "SELECT * FROM prod_designs WHERE pd_year = '$year'");
while($row_search = mysqli_fetch_array($search)) {
EDIT
I have tried to build out the "WHERE" in the query dependent on the is_array check like this:
$where = "WHERE ";
if(!empty($pd_year_ex) && is_array($pd_year_ex)) {
$pd_y = $pd_year[0];
foreach ($pd_y as $year) {
$where .= "pd_year LIKE '%".$year."%'";
}
} elseif(!empty($pd_year_ex) && !is_array($pd_year_ex)) {
$where .= "pd_year LIKE '%".$pd_year_ex."%'";
} elseif(empty($pd_year_ex)) {
$where .= "";
}
and this doesn't seem to be working either. i am just trying to understand how to do a search like this:
$search = mysqli_query($con, "SELECT * FROM designs WHERE pd_year LIKE '%2017,2016,2015%'")(etc)
I know it won't go with the above, but how do i search a table for something like this?

Variable sql query depending on number of search parameter

I need to do a sql query in php for search some entries (so using WHERE). But the field used to search could be of variable number.
I have a page with a search form, with 4 Field. It sends via POST the fields to a search.php that make a query:
$gomme_sql = $data->query("SELECT * FROM table WHERE parameter1 = '$_POST['name1']' AND parameter2 = '$_POST['name2']' ORDER BY id ASC");
But I don't know which field are filled. So, if I don't enter anything in field1 from the search form, I shouldn't have parameter1 = '$_POST['name1']' in the WHERE query.
Have you any idea how to obtain this?
Thank you
You can check the post data before appending that clause to the query in a way like this:
edit: adding additional check:
$sql="select something from someTable ";
if(!empty($_POST['name1']) || !empty($_POST['name2'])) // add as many as you like
{
$sql.=" where ";
if(!empty($_POST['name1']))
{
$sql.="parameter1= $_POST['name1']";
}
// etc etc...
}
$sql.=" ORDER BY id ASC";
and so on.
Having said that, please, please use prepared statements with this sort of input from the user. This is SUPER open to sql injection. Please do read this: How can I prevent SQL injection in PHP?
You can write generic sql select function like this , if you need more complex SQL just modify it.
<?php
function sqlSelect($table, $sel, $wh = '', $groupby = '', $order = '', $add = '') {
$tb = $table;
if (is_array($table)) {
$tb = implode(',', $table);
}
if ($wh) {
if (is_array($wh)) {
$w = array();
foreach ($wh as $k => $v) {
$v = mysqli_real_escape_string($v);
if (is_null($v))
$w [] = "$k=null ";
else
$w [] = "$k ='$v'";
}
$wh = 'where ' . implode(' and ', $w);
}else {
$wh = "where $wh";
}
}
if ($groupby)
$groupby = "group by $groupby";
if ($order)
$order = "order by $order";
$sql = "select $sel from $tb $wh $groupby $order $add ";
return $sql;
}
//set _GET as this is console test
$_GET['name1']='Bob';
$where = array(
'name1'=>$_GET['name1']
);
echo sqlSelect('sometable' , '*' , $where) ."\n";
// select * from sometable where name1 ='Bob'
//or some complex stuff
echo sqlSelect('persons', "age,status" , array('name'=>'Maria' , 'likes'=>'PHP') , null, 'age' , 'limit 20');
//select age,status from persons where name ='Maria' and likes ='PHP' order by age limit 20

if field is empty, return all results

I'm working at a search script at the moment, but I have a little problem. I'm using the following query:
mysql_query("SELECT * FROM boeken WHERE
titel LIKE '%".$titel."%' AND
categorie_id = '".$categorie."' AND
auteurs LIKE '%".$auteurs."%' AND
jaar_copyright = '".$jaar_copyright."'
AND ontwerp_groep = '".$ontwerp_groep."'");
For example, when I search for 'categorie_id' = '5', and leave the other fiels empty, I want to get every row that has categorie_id = 5. No matter what the other fields are.
What it does is the following: I get every row that has categorie_id = 5, but where the title is empty, where the 'jaar_copyright' is empty, etc. etc.
How can I fix this the way I want?
<?php
$query = "SELECT * FROM boeken WHERE";
$n = 0;
$makeAnd = "";
foreach($_POST as $key=>$value){
if($value != '' && $value != 'submit'){
if($n != 0){$makeAnd = " AND";}
if(!is_numeric($value)){
$query .= "$makeAnd `$key` LIKE '%$value%'";
} else {
$query .= "$makeAnd `$key` = '$value'";
}
$n++;
}
}
print $query;
?>
In this way you can filter out empty values. If other values are posted to $_POST make sure to filter them out in the "if($value !=" part.
Why not just build a query based on vars? That way they're not included in the query unless the var is populated. I don't know what your variables like $titel actually are, so I just say if they're not blank. This should obviously be set towhatever is applicable. Not null, isset, etc. and always escape with something like mysql_real_escape_string()
$titel_where = "";
if($titel != '')
$title_where = "AND titel LIKE '%".$titel."%'";
$auteurs_where = "";
if($auteurs_where != "")
$auteurs_where = "AND auteurs LIKE '%".$auteurs."%'";
$jaar_copyright_where = "";
if($jaar_copyright != '')
$jaar_copyright_where = "AND jaar_copyright = '".$jaar_copyright."'";
$ontwerp_groep_where = "";
if($ontwerp_groep != '')
$ontwerp_groep_where = "AND ontwerp_groep = '".$ontwerp_groep."'";
mysql_query("SELECT * FROM boeken WHERE
categorie_id = '".$categorie."'
$titel_where
$auteurs_where
$jaar_copyright_where
$ontwerp_groep_where
");
mysql_query("SELECT * FROM boeken WHERE
( '".$categorie."' = 5 AND
categorie_id = 5
) OR
( titel LIKE '%".$titel."%' AND
categorie_id = '".$categorie."' AND
auteurs LIKE '%".$auteurs."%' AND
jaar_copyright = '".$jaar_copyright."' AND
ontwerp_groep = '".$ontwerp_groep."'
)");
For each criteria, you need to add a second evaluation for a blank parameter value:
(categorie_id = '".$categorie."' OR '".$categorie."' = '') AND ...
This way you cover both cases of an empty or a populated parameter.
EDIT:
Sample query as it would appear in SQL.
Assume you pass in a $categorie of 5 and no other parameters:
SELECT * FROM boeken WHERE
(titel LIKE '%%' OR '' = '' )AND
(categorie_id = '5' OR '5' = '') AND
(auteurs LIKE '%%' OR '' = '') AND
...
If they get passed in as NULL then do a NULL comparison instead of an empty string comparison.
You should check what field is set in code, and then only add that part to your query. for instance:
if(isset($_POST['categorie_id'])){
$where = " categorie_id = '".$categorie."' ";
}elseif(...){
....
}
Well, you get the point, you can make it a bit neater probably, depending on the format of your form/POST etc, but that's the idea. Just figure out WHAT you know, and then push it in the SQL.
I'm at work, so no long stories possible, but you should be able to figure it out with this:
foreach($_POST as $key=>$item){
if($value != ''){
$yourField = $key;
$yourValue = $item;
}
}
//PERFORM SANITY CHECKS!
//MAYBE USE PDO etc? (but that's another thing)
//SAVE them in 2 new variables used below:
$query = "SELECT * FROM boeken WHERE `$sanitizedField` = '$sanitizedValue'";

select from mysql db with 300 tables using a default prefix

I have a program that selects from about 200 tables with prefix. eg PBN_products, PBN_address, PBN_others.
Instead of appending the prefix on each table for the select statement, is there a way of defining the prefix as default value and do the selection?
$prefix=GET['prefix'];
mysql_connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD);
mysql_select_db(DB_DATABASE);
$sql = 'SELECT price, description, title, cost'.
'FROM products, address, others';
How can I define the prefix not to include in all tables? I have 200 tables.
I would look into a class to do some simple query abstraction or some kind of ORM lib that does this. A sample would be like this.
class Query {
function from($tbl){
return new Table($tbl);
}
}
class Table {
var $prefix = 'PBN_';
var $tblname = '';
function Table($name){
$this->tblname = $this->prefix.$name;
}
function select($cols, $where = false, $order = false, $limit = false){
$query = "SELECT {$cols} FROM {$this->tblname}";
if($where) $query .= " WHERE ".$where; //add where
if($order) $query .= " ORDER BY ".$order; //add order
if($limit) $query .= " LIMIT ".$limit; //add limit
return $query;
}
}
$q = new Query;
$results = mysql_query($q->from('products')->select('*'));
This is obviously nowhere near complete or secure. Just a sample of how an abstraction class could speed up your sql and do you your prefixes for you.
You could define an array with the table names, and loop through that array. When you append the array item to the string, put "PBN_" hardcoded in front of that name.
$arr = array("products","address","others");
$sql = "SELECT price, description, title, cost FROM ";
foreach ($arr as $tablename) {
$sql = $sql . "PBN_" . $tablename . ", ";
}
$sql = substr($sql, 0, -2); // Remove last comma
You can then add all the tablenames to the array, and the prefix will automatically be added.
How about something like this?
$prefix = GET['prefix'];
// add prefix to table names
foreach (array("products", "address", "others") as &$table)
{
$table = $prefix.$table;
}
mysql_connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD);
mysql_select_db(DB_DATABASE);
$sql = 'SELECT price, description, title, cost'.
'FROM '.$table[0].', '.$table[1].', '.$table[2];
You could do something like this?
$prefix = '';
if(isset($_GET['prefix'])){
$prefix = mysql_real_escape_string(stripslashes($_GET['prefix']));
}
$sql = "SELECT price, description, title, cost
FROM {$prefix}products, {$prefix}address, {$prefix}others";
EDIT: I agree on the comments that this is bad practice... An alternative would be to store the prefixes in another table and pass an ID of that table in the GET. This would make you less vulnarable to SQL injections.
$prefix = "";
if(isset($_GET['prefixid'])){
$prefixid = mysql_real_escape_string(stripslashes($_GET['prefixid']));
$query = "SELECT prefix FROM prefixes WHERE prefixid = $prefixid";
$result = mysql_query($query);
$prefix = mysql_result($result, 0, 0);
}
$sql = "SELECT price, description, title, cost
FROM {$prefix}products, {$prefix}address, {$prefix}others";

How can execute a MySQL query with multiple WHERE-clauses?

how would you do a mysql query where a user can choose from multiple options. Fox example I have a form that user can use to search for houses. Now I have a select box where you can chosse whether you want a house, a flat or whatever. Then I have a second box where you can choose for example the city you want the house or flat to be in. And maybe another one with the maximum price.
Now how would you do the mysql query? My problem is, I would do it like that:
if($_POST["house_type"] != 0) {
$select = mysql_query("SELECT * FROM whatever WHERE type = '".$_POST["house_type"]."'");
}
But now I only have the case that someone has chosen a house type but not any other option. So do I have to do an "if" for every possible combination of selected elements?
To emphasize my problem:
if(!isset($_POST["house_type"])) {
if($_POST["something"] == 0) {
$search_select = #mysql_query("SELECT * FROM housedata WHERE something = $_POST["whatever"]);
}
elseif($_POST["something"] != 0) {
$search_select = #mysql_query("SELECT * FROM housedata something = $_POST["whatever"] AND somethingelse = 'whatever');
}
}
elseif(!isset($_POST["house_type"])) {
if($_POST["something"] == 0) {
$search_select = #mysql_query("SELECT * FROM housedata WHERE something = $_POST["whatever"]);
}
elseif($_POST["something"] != 0) {
$search_select = #mysql_query("SELECT * FROM housedata something = $_POST["whatever"] AND somethingelse = 'whatever');
}
}
Now imagine I had like 10 or 20 different select boxes, input fields and checkboxes and I would have to do a mysql query depending on what of these boxes and fiels and checkboxes is filled. This would be a code that is extremely complicated, slow and horrible. So is there a possibility to make a mysql query like:
SELECT * FROM whatever WHERE house_data = '".$whatever."' AND (if(isset($_POST["something"])) { whatever = '".$whatever2."' } AND ...;
You get what I mean? Its a bit complicated to explain but actually its a very important question and probably easy to answer.
Thank you for your help!
phpheini
Generate the WHERE clause prior to running the SQL.
A short example:
$whereClause = "";
if ($_POST['opt1']) {
$opt1 = mysql_real_escape_string($_POST['opt1']);
$whereClause .= "AND opt1='$opt1'";
}
if ($_POST['opt2']) {
$opt2 = mysql_real_escape_string($_POST['opt2']);
$whereClause .= "AND opt2='$opt2'";
}
mysql_query("SELECT * FROM table WHERE 1 ".$whereClause);
To point you a little bit into the right direction, try something like this:
if(isset($_POST["something"]))
{
$where = " AND whatever = '".$whatever2."'";
}
else $where = '';
mysql_query("SELECT * FROM whatever WHERE house_data = '".$whatever."'".$where);
$where = array();
if($_POST["something"]) {
$where[] = " something =".$_POST["something"];
}
if($_POST["something2"]) {
$where[] = " something2=".$_POST["something2"];
}
.
.
.
//build where string
$where_ = !(empty($where) ? " WHERE ".implode(" AND ",$where) : "";
//build sql
$sql = "SELECT * ... ".$where;
write some simple query builder
$where = array();
if($_POST["something"]) {
$where[] = sprintf(" something='%s'",$_POST["something"]);
//sprintf - prevent SQL injection
}
if($_POST["something2"]) {
$where[] = sprintf(" something2='%s'",$_POST["something2"]);
}
//build where string
$where_str = " WHERE ".implode(" AND ",$where);
//build sql
$sql = "SELECT * ... $where_str";
You need to build your search string separately but the format is simply
SELECT * FROM your_table WHERE number = {$number} AND sentence = '{$sentence}';
Since you are creating the search term based on PHP logic do this:
$search = "SELECT * FROM your_table WHERE ";
if(isset($whatever)) $search .= "something = '{$whatever}'";
if(isset($whateverelse)) $search .= " AND somethingelse = '{$whateverelse}'";
$search_select = mysql_query($search);

Categories