I've searched this relentlessly and I cannot find an answer to my quandary - I think the problem is that I'm not exactly sure WHAT to search for! Anyhow, my problem is this...
Scenario:
Imagine having a database of, for arguments sake, recipes and you wanted to give users the ability to generate a list of recipe suggestions based on various criteria.
In the form of a web page, I would want this to be a series of drop down boxes on the left. The user would select their filter options from the drop down boxes and, after pressing the submit button, would be presented with a list of recipes that fit the criteria.
So they could, for example select 'Meal Type', 'Calories', 'Cooking Time' and then (after hitting submit) get back a list of recipe suggestions that fit the bill.
(Ideally they would appear without the need for reloading the page and would be contained within a slider to browse through, but I can probably crack that part if I get the underlying part sorted...)
Requirement:
I just need to know - at a top level - which technologies I would use to achieve this (and the process of how they work together).
I'm guessing I'd need a MySQL dB with recipes that are tagged with criteria, then use the form and php to pull from the database. Is this correct?!
Seems like such a common requirement, but I can find no good reading on how to achieve this..
Take a look at the PHP guide to prepared statements. You'll be basically writing a select statement against the table where your data resides, with the where clause of the select statement being the parameters selected by your user in the form.
PHP Prepared Statements
The reason you want to stick to prepared statements is that they are generally more secure against attacks on your site via the form, using SQL injection.
For the end to end solution, your front end will submit to a PHP page which will then handle the criteria specified by the user, translating those into the prepared statement which will find the data from your table. The table itself will need to have columns which correspond to the criteria. That gets more into database design which is a much larger topic to cover here, however there are plenty of guides out there for that.
Really you want to break the solution down into the subcomponents, then find various guides out there to tackle the parts. Good luck, hope this helps. :)
The process:
1) User makes selection and clicks submit button. That will initiate a HTTP POST to a PHP page (can be the same PHP page) where you would collect these information.
2) Open a MySql database connection with PHP. You would need to know SQL to pull data from MySql DB. Depending on how your database schema is laid out.
3) Once you pull this information display them as a checkbox where user can click.
This is the bare minimum.
If you wanna get a bit more fancy you can use JQuery ajax post (http://api.jquery.com/jQuery.post/) so the page does not refresh.
Good luck and I'm already hungry. haha.
When the user selects options in your form and submits it, this will run a PHP script on the server. The server retrieves the option parameters, and uses them to construct a SQL query. For instance, the script might contain something like:
$criteria = array();
if (isset($_POST['calories'])) {
$criteria[] = 'calories < '.$_POST['calories']);
}
if (isset($_POST['time'])) {
$criteria[] = 'cooking_time < '.$_POST['time']);
}
...
$query = 'SELECT * FROM recipes WHERE '.implode(' AND ', $criteria);
You use a library like mysqli or PDO to perform the query and get the results. Then you loop through the results, and format them into an HTML table which will be returned to the user as the resulting web page.
Or the PHP script could return the results as JSON data. Your web page could use AJAX to get this data from the server, then use JavaScript to format it into a table.
Related
I'm going over my old system and updating the old, deprecated code from mysql to PDO and just giving it a general makeover. The system basically grabs data from the database, displays it in a fancy table and its then sortable by clicking on the table headers or by changing the search filters by the side. (e.g having a drop down box of different categories)
It's been a right nightmare updating the old system because the code is just all over the place. It currently gets the search filters information from the URL via GET and dynamically creates a query string. This makes it even more complicated when working with prepared statements.
Is there anything out there that can help me avoid a headache? I'm looking for something that allows me to display information from a database and also has the options to add search filters. I could probably build one from scratch but I just don't want to waste the effort on something that has (probably) already been solved.
I personally like using datatables. It can process large datasets very quickly and all of that sorting you talked about is a feature with datatables.
https://datatables.net/
I have discovered that some old (2009) code that was written for a website, did, under certain circumstances on a search query save the SQL as a a $_GET variable!
When the search was carried out, the details are POSTED and then sanitized, and the results are paginated with the LIMIT clause in MySQL. If there is more than one page (ie +30 results) the pages are anchor links in the HTML with a GET var containing the SQL statement.
I know, this is absolutely not the way to do this. It's old code I've just seen it by chance. This needs to be fixed.
So I've fixed it, sanitized it and used an alternative method to reload the SQL, BUT:
My question is thus:
The page outputs the data relating to thumbnail images, all data is output as named array var (the original clause is a SELECT * clause), so if someone does abuse the GET variable, the page itself will only output the columns named,
I have managed to DELETE rows from the DB using the GET abuse, I would like to think the abuse is only effective if the result is not involving any returned output (such as DELETE) but I don't know; so given that the user can input anything into the GET clause but only get the displayed output of what's coded (ie named columns in a 30 row array) -- what other abuses can this gaping hole be open to?
Further details: The code is MySQLi
A tool like SQLMAP can probably take over the entire server and do with it whatever the user wants.
Having an unsanitized database input isn´t even hacking anymore, it´s waiting for someone to run a script on your machine and basically own it from that point on.
What the attacker can do depends on your database configuration and database user access. If you create a new user with a permission to only SELECT that one specified table, and use that user for that particular script, the harm it can do is reading data from that table.
Still this is bad practice. Never use it.
I have created a very simple CRUD that queries my database for Hotel details and displays them within an HTML table.
By default my mysql query returns the Hotels in the order they were created. I have come up with a few different sql statements to return results by distance or A-Z and I would like the user to select which they prefer.
How can I create a simple dropdown with for example "Name" and "Distance", which when selected will reload the page using the correct sort query using PHP?
Your basic structure is going to look like;
HTML;
<SELECT id="sort_select" onchange="javascript:re_sort();">
//options
</SELECT>
Javascript function;
function re_sort() {
//make ajax call using sort_select value
//refresh table contents
}
PHP;
if($_GET['sort_field'] == 'fish') {
//execute fish sort sql
}
else if($_GET['sort_field'] == 'goat') {
//execute goat sort sql
}
//return response
Do Not use the $_GET value directly in the sql query, instead use the structure above.
Sounds simple enough. You add an ORDER BY clause populated by the value from the dropdown.
Fair Warning!
Direct user input is highly dangerous! And prepared statements cannot be used on an ORDER BY value. You'll need very aggressive whitelisting, make sure the value you receive is one of pre-defined values, which are fetched from somewhere on the server (the database schema, or hardcoded into the PHP code).
Never let user input arrive your query unchecked and unsanitized!
More information about SQL Injection.
You will need to use JavaScript that handles the change event and reload event. However, you will want to handle disabled JavaScript browsers too. You can do that by maybe showing a sumbit button and hiding it with the JavaScript.
As far as PHP there are several ways to approach it, but here is an idea. Store the sorting values into an array. Then have the index be a number, just so SQL injection will not take place if done right as we do not want to allow pure SQL statements. When the user changes submit it.
In the code have a switch and append the appropriate SQL statement to it based on the number input.
I have my Search Results being displayed just fine, but I have several categories. I want to be able to select the Column and use ORDER BY. Here's what I have to try and do this.
<a href='searchresult.php?db=members&table=people&sql_query=SELECT+%2A+FROM+%60people%60+ORDER+BY+%60lastname%60.%60level%60++DESC+%60AGAINST+$search&token=5e1a18b6cccb5db7a37bb3fce055801a'>Last Name</a>
the $search is what I search for. and when I look at the link it shows what I searched for in its place. So I figured this would work, but of course it did not. What would be the right way to set this up for each one of my columns so when I click the link it will sort my results in the order of that column?
Thanks!
The first thing that should SCREAM at you is to NEVER run any SQL query that contains any input that could possibly come from a client without first sanitizing it. Running an entire query from (potentially) user input will allow them to run a command like DROP DATABASE or TRUNCATE TABLE, or worse, they could get sensitive information out of it.
So you should hard-code your SQL query and just take the user input for the specific values you are querying for, but first sanitize those, by doing something like this:
$query = sprintf("SELECT * FROM 'people' ORDER BY %s DESC", mysql_real_escape_string($_GET["orderby"]));
Now, on to your actual question...after the page has been loaded, you have two options:
You could re-query using AJAX.
You could sort the table using Javascript.
Which is better really depends on how many rows you are expecting.
If you are fetching a lot of rows, sorting via Javascript starts getting pretty slow, but if it's just a few rows (like less than 100 or so), then Javascript is probably the way to go. I don't know much about other libraries, like JQuery or otherwise, not sure if they have a better solution. So for a lot of rows, using AJAX to just re-query the database is probably faster.
However, if your page consists of just this table by itself, there's not really any point in using AJAX as opposed to just refreshing the page with a different query.
If you do decide to sort the table using Javascript, a library like this one might help. Or just google "javascript sort table".
I'm putting together a practice site utilizing PHP and MySQL to replicate (or closely resemble) this site. As of right now my searchable fields include: Rent (min-max), Type of rental (any, apartment, house), Number of Bedrooms (any, 1+, 2+, 3+, 4+)
I'm not having trouble with putting together the code thus far, I'm just worried about scaling issues and want to know what is considered best practice. Also, any advice for how to replicate the 'Sidebar filter search' that is on the site I linked (eBay also has something very similar) would be awesome.
Here is where I've hit a fork in the road: Do I individually process each field filter in a MySQL query or do I call all items in a table and then filter them in PHP?
$sql = "SELECT * FROM properties ";
$properties = Property::find_by_sql($sql);
$matched_properties = array();
foreach($properties as $property):
if ($min_rent <= $property->rent && $property->rent <= $max_rent) {
$matched_properties[] = $property;
}
endforeach;
The code above pulls everything from 'properties' table in MySQL and makes a Property classes (basic CRUD class) array.
Apologies if I sound jumbled, but my main question is How can I replicate a filtered search such as that on this site OR eBay.com? And am I on the right path?
Thank you
Generally speaking, the less data you have to pull from your database to process in PHP, the better. Less code you have to write, less resulting bugs, less data to transfer through the software stack, etc. etc. You may need to read up on how to write more complex SQL queries. The following would be a much more efficient version of the code snippet you gave:
$sql = "SELECT * FROM properties WHERE rent >= $min_rent AND rent <= $max_rent";
$matched_properties = Property::find_by_sql($sql);
For security though, you'd need to make sure $min_rent and $max_rent are validated as real numbers. (Hint: pass the inputs through is_numeric() and throw an error if this function returns false.) Otherwise a hacker could perform what's known as a Code Injection, entering other snippets of SQL query strings in place of "min_rent" or "max_rent" to make your query do lots of undesirable things.
As for implementing a filtering mechanism like that U of Iowa site, it's a matter of having links or a form in the sidebar that refreshes the page when clicked. You can do this several ways. The coolest way is probably using AJAX to automatically update the main content window. The U of Iowa site doesn't seem to be doing this, because when I click various filter links in the sidebar, the entire page refreshes instead of just the main content area.
jQuery is a really helpful JavaScript library that can help you do AJAX with minimal coding. Check it out. Basically, you'll want to build your filter sidebar so that each link clicked causes an AJAX query to your server, which pulls in an updated data set based on the user's selected filters. When the result comes back from the AJAX call, you can use JavaScript and/or jQuery methods to inject the data as needed into your page.
Good luck!