First - my code works and no problem with that, but it is not completely safe.
I don't know how to bind my query. I know a bout bindParam / bindValue but i don't have any idea how to use those in my case...
My query consists of part and the parts depends of AJAX post:
if(!empty($_POST['manufacturers']))
$manufacturers = $_POST['manufacturers'];
else
$manufacturers = null;
if(!empty($_POST['processors']))
$processors = $_POST['processors'];
else
$processors = null;
if($manufacturers != null)
$manufacturers = ' AND manufacturer.slug IN('.$manufacturers.')';
if($processors != null)
$processors = ' AND processors.slug IN('.$processors.')';
And complete query will be:
$query = "bla bla my query";
$query = $query.$processors.$manufacturers;
Example query is:
SELECT manufacturer.name AS ManufName,
model.model_name AS ModelName,
processors.name ProcName,
laptops.resolution,
inches.name,
graphic_card.name GraphName,
laptops.memory_type,
laptops.memory_size,
laptops.ram,
laptops.price,
laptops.image_path
FROM manufacturer, model, processors, inches, graphic_card, laptops
WHERE manufacturer.id = Laptops.manufacturer_id
AND model.id = Laptops.model_id
AND inches.id = Laptops.inches_id
AND processors.id = Laptops.processor_id
AND graphic_card.id = Laptops.graphic_card_id
AND manufacturer.slug
IN('Dell','Lenovo')
AND processors.slug
IN('Intel_core_i5','Intel_core_i7')
And from post i get in this case: 'Dell','Lenovo' and secondly i get:
'Intel_core_i5','Intel_core_i7'
Query changes by every checkbox change from user interface...
So if user checks only checkbo from manufacturers then the query will not be the same if query checks checkboxes from both - manufacturers and processors...
I need to prevent things like this:
$.post('ajaxCallback.php', {manufacturers: 'sleep(15)'});
How to bind this query or how to make this correctly safe?
I appreciate any help and advice!
Thanks a lot!
Related
Is there any way to run mysqli query dynamically ? I am working on a small project who has dynamic form generation option. And then they want to filer those forms. Obviously we dont know how much will be form fields and how many filters they want. So is there any such way through which I can perform this action? Suppose if i can do something
SELECT * FROM table WHERE fld1 = 1 OR fld2 = 2 OR fld3 = 3....
Where those 1, 2, 3,... Can be something or maybe its empty depend on filters.
You can dynamically build your query in php by examining your $_POST values and then building out your where statement. Here's some pseudo code
foreach($_POST as $name=>$value)
{
$where[] = "`$key` = '$value'";
}
$sql = "SELECT * FROM table WHERE ".implode("OR", $where);
Of course you will need to either sanitize or use a prepared statement to make sure this is safe.
The best way to run it dynamically is by using PDO and classes, if youre confused about any of those two things check out the PHPGuru Jeffery Way found here: https://laracasts.com/series/php-for-beginners and check out his PHP tutorials, youll quickly learn what you need to do to be able to make a class that allows you to dynamically connect to your database!
Maybe do something like:
$Where = array();
foreach($_POST['form-field'] as $Field=>$Value){
if($Value){
$Where[] = $Field."=".$Value;
}
}
$Query = "SELECT * FROM table WHERE ".implode(" OR ",$Where);
You can use IN clause of in MySQL query.
Similar like this.
SELECT * FROM table
WHERE fld1 IN (1, 2, 3);
Hope this will help you.
$filter = '';
$filter .= 'fld1 = 1 OR ';
$filter .= 'fld2 = 2 OR ';
$filter .= 'fld3 = 3 OR ';
...
...
if(!empty($filter)) {
$filter = substr($filter,0,-2); // delete last OR
}
$query = "SELECT * FROM table WHERE ".$filter."";
...
Something like this would work, you have to modify the way you populate $filter
Hope this'll help.
I'm trying to create a dynamic search query, based on the user input.
Requirements:
A user could fill in none, some, or all fields.
The query searches in a table for a record that matches all the requirements.
Now I have done my research, and I found out multiple ways on doing this. But none of them work, and if they do, they are far from practical.
Attempt:
At the moment I'm creating a query like this:
SELECT *
FROM assignments
WHERE (id = $id OR id = '')
AND (field1 = $field1 OR field1 = '')
This query works, but only if you fill in all the fields.
I got this from a stackoverflow article, that I can't find anymore, that said:
If the user has filled in an input field it will check the first rule
"id = $input"
and if the user hasn't specified any input it will check for "id = '' " and when it
checks for that, it will just return everything. Because it escapes the empty search rule.
But as you might already know, it doesnt work..
How would you suggest me to approach this?
Try getting all of the post vars and looping through them to see if they are valid, and then build your query
<?php
$id = $_POST[id];
$field1 = $_POST[field1];
$field2 = $_POST[field2];
$field3 = $_POST[field3];
$whereArr = array();
if($id != "") $whereArr[] = "id = {$id}";
if($field1 != "") $whereArr[] = "field1 = {$field1}";
if($field2 != "") $whereArr[] = "field2 = {$field2}";
if($field3 != "") $whereArr[] = "field3 = {$field3}";
$whereStr = implode(" AND ", $whereArr);
$query = "Select * from assignments WHERE {$whereStr}";
Something like that should handle what you need
You should start with a string like yours up to the WHERE statement, then after that you loop through all the fields the user wants to search with and add them to an array, then use the PHP function "implode" to glue the fields together with an AND statement as "glue".
Now add on the glued string to the startquery and voila!
I'd give example but on phone atm!
Building the query dynamically based on the responses is definitely a must. But another nice feature that allows users to find results based on even partial responses is using a MySQL REGEXP query. So for instance, if they wanted to find "maverick" in a Top Gun database, a query REGEXP = 'mav' | 'rick' would return results. This brings your search much closer to the search engine functionality that users are accustomed to.
Here's a REGEXP example, simplified.
I need help with building a query, I have a form ( multiple dropdowns) and need to display a data table according to the user selection.
filters.php (on server side - ajax )
$criteria[0] = $_POST['Size'];
$criteria[1] = $_POST['Name'];
$criteria[2] = $_POST['Color'];
$criteria[3] = $_POST['Sku'];
$criteria[4] = $_POST['Features'];
$statement = $dbh->prepare("select * from table_name where Sku = :sku AND Size = :size AND Color = :color AND Features LIKE :features ");
$statement->execute(array(':name' => $criteria[1], ':Size'=> $criteria[0], ':color'=>$criteria[2], ':sku'=>$criteria[3], ':features'=> '%'.$features[4].'%'));
$statement->setFetchMode(PDO::FETCH_ASSOC);
$subrows = $statement->fetchAll();
// ect..
When all the criteria are selected ( all dropdowns have a value ) the call will return data , but what if the user only selects one, two or three dropdowns? It will return an empty table which is logic if using the query above.
I was thinking maybe I should try first to check if the variables are set, then perform for each scenario a query ? Im kind of lost how to implement it.
The idea is to have a small div with dropdowns next to the data table which allows filtering.
thanks
If statements dependent on the $_POST key may be the best way - and add the corresponding part to the query string:
i.e. :
$queryString = "select * from table_name where ";
if($_POST['SKU']){
$queryString .= "Sku = :sku";
}
Furthermore, to handle the "AND" parts :
$and = (count($_POST) > 1 ? 1 : 0);
and inside each if statement, the first line should be:
$queryString .= ($and ? "AND " : "");
Furthermore, I would suggest using an ORM, (Idiorm being my personal favorite, which I use in this example: )
$queryBuilder = ORM::for_table("table");
if($_POST['Sku'])
$queryBuilder = $queryBuilder->where("Sku", $_POST['Sku']);
and so on and so forth.
Check the desired variables to see if they contain data, if so you have to build the query. You can add to the array at the same time! For example:
$myarray = array();
if(!empty($criteria[0])){
$myarray["Size"] = $criteria[0];
}
I am trying to have filters dropdown in my CMS
my model looks like
public function load($sort,$order,$key,$value)
{ // $key='listening'; // $value="1";
//configure pagination
$config=array(
'base_url'=>base_url().'/index.php/companies/index',
'total_rows'=>$this->db->get('company')->num_rows(),
'per_page'=>$this->settings_model->get_per_page(),
'num_links'=>20
);
$this->pagination->initialize($config);
$this->db->select('company.id,
company.name,
company.logo,
company.status_id,
company.listening',FALSE);
$this->db->select('company_category.name as category,
company_category.id as category_id',FALSE);
$this->db->select('complain_status.cs_status as status',false);
$this->db->from('company');
$this->db->join('company_category','company_category.id = company.category_id');
$this->db->join('complain_stastus', 'complain_status.cs_id = company.status_id');
if(isset($_POST['key']))
{
$value= str_replace(' ', ' ', $_POST['value']);
var_dump($value);
if($value!='0')
$this->db->having ($_POST['key'], mysql_real_escape_string($value) );
}
if($sort!='' || $sort!=NULL)
$this->db->order_by ($sort, $order);
$this->db->limit($config['per_page'], $this->uri->segment(3));
$result=$this->db->get();
if(!isset($_POST['key']))
$this->filter->set_filters_list($result->result_array());
return $result->result();
}
that generates the below query
SELECT company.id, company.name, company.logo, company.status_id, company.listening, company_category.name as category, company_category.id as category_id, complain_status.cs_status as status
FROM (`company`)
JOIN `company_category` ON `company_category`.`id` = `company`.`category_id`
JOIN `complain_status` ON `complain_status`.`cs_id` = `company`.`status_id`
HAVING `category` = 'Health & recreation'
LIMIT 20
as you can see here is the problem when category equals some string with special character like Health & recreation it fails and even if i tried the query generated by CI it works normally on MYSQL and gets me the result
Note : I m replacing the space $value= str_replace(' ', ' ', $_POST['value']); as this data comes from select html element that fails when it has spaces in options so i had to parse and remove it later in the back-end code
Thanks in advance
Code igniter is probably html_encoding the ampersand so that it reads as its html value. YOu can comfirm this by turning on the profiler by adding this line to the constructor of whatever controller or model your runnning the query in:
$this->output->enable_profiler(TRUE);
if I'm right your query will have substituted something like & where the & should be.
Note the profiler reveals the & while using a $this->db->last_query() still shows a &
To insert symbols into the database, you need to escape the values first. In PHP, you would normally use: mysql_real_escape_string()
How to insert special characters into a database?
However, as you're doing this in CodeIgniter, you have to use query binding for the data to automatically be escaped,
$category = $this->input->post('category');
$status = $category = $this->input->post('status');
$status_id = $category = $this->input->post('status_id');
$sql = "SELECT * FROM company WHERE category = ? AND status = ?";
$this->db->query($sql, array($category, $status));
http://ellislab.com/codeigniter/user_guide/database/queries.html (under Query Binding)
Does CodeIgniter automatically prevent SQL injection?
Although its not part of the original question, your code has flaws in that your using $_POST['value'] without any sort of filtering. There would be nothing stopping someone from SQL injecting your form.
How can I prevent SQL injection in PHP?
I need some guidance to make an advanced search script for a website I'm working on.
I already know how to search the database for simple queries. The problem I'm encountering right now is how to search, when using multiple select boxes. For example:
This is just a simple form with different search options. The question is:
The visitor can choose to search on a country or city, both or even with all three options.
How do I catch that in the PHP script? Do I have to check if for example a city has been chosen, and fire a query based on that? But if I do that I would have to make different queries based on each select option.
In pseudo-code it would be something like this: (I imagine)
if country and city and something else is not null, launch a query to search in all three tables in the database.
But what to do when just the country has been chosen? Or just the city?
Is there a simple way to accomplish this?
Thanks in advance.
I like using an array to join conditions so I don't have to worry about leading or trailing AND's.
$conditions = array();
if ($formCondition1) {
$conditions[] = 'state = "'.$somevalue.'"';
}
if ($formCondition2) {
$conditions[] = 'country = "'.$somevalue.'"';
}
...
if ($formConditionN) {
$conditions[] = 'N = "'.$somevalue.'"';
}
//finally join the conditions together, the simplest case is with ANDs (if you need to add ORs, which it sounds like you don't, then this code would be a bit more complex)
$sqlStatement = 'SELECT field1, field2 FROM tableABC WHERE '.implode(' AND ', $conditions);
EDIT: don't forget to escape the input to prevent injection attacks, and of course test to make sure there are at least 1 condition before running the query.
EDIT: lol jswolf and I think very much alike :)
I make a $where array, add my conditions to it as necessary, and then implode it with ' AND ' as the glue. So something like:
$where = array();
if $city is defined
$where[] = "city = '".mysql_real_escape_string($city)."'";
fi
if $country is defined
$where[] = "country = '".mysql_real_escape_string($country)."'";
fi
...
if(count($where)) {
$query.= ' WHERE '.implode(' AND ', $where);
}
I would try something like:
$qry = "SELECT * FROM table WHERE ";
if ($country != '') {
$qry .= "country='".mysql_real_escape_string($country)."' AND "
}
if ($city != '') {
$qry .= "city='".mysql_real_escape_string($city)."' AND "
}
$qry .= '1';
$res = mysql_query($qry);
The query is built up depending on what is set. Note the "1" on the end of the query string which is always true. This is needed to follow the "WHERE" if $country and $city are both empty, or to follow the last "AND" if they are not.