PHP: sorting out in a smart coding way? - php

So i have this videosection, but i want to make a "sorting" option avaible for users.
Sorting Options: ALL (no WHERE in the sql statement), Videoklips (WHERE SCtry = 0), SC try (WHERE SCtry = 1)
Now, i know how to do it "my" way. I would have placed links on index.php:
?sort=video and ?sort=SCtry
Then make 2, if sort video, if sort sctry
and then duplicate the whole index.php right now(which displays everything) into the 2 if's and then just edit the SQL statement SELECT, with WHERE SCtry = '0' on ?sort=video, and WHERE SCtry = '1' on ?sort=SCtry.
Now, i KNOW how to sort out, but i want to code it in a smarter way (if it exists, of course), because this seems to be too much to duplicate the whole site and then just only change 1 line...
Example of what i ment with index.php, that i am going to duplicate:
<?php
$hent_meetup = mysql_query("SELECT * FROM member_film ORDER BY id DESC LIMIT 0,200") or die(mysql_error());
while($vis = mysql_Fetch_array($hent_meetup)) {
?>

without seeing example code, I can tell you this is an example of what I'd do.
<?
//all of the code before the SQL statement here...
$sql= ' SELECT `column` from `tablename`'; //or any other SQL that is appropriate before the conditional
if(isset($_GET['sort'])){
if($_GET['sort'] == 'video'){
$sql .= ' WHERE `SCtry` = 0';
}elseif($_GET['sort'] == 'SCtry'){
$sql .= ' WHERE `SCtry` = 1';
}
}
$sql .= ' ORDER BY `whatever`'; //or any other SQL that is appropriate after the conditional
//rest of code... no need for duplication
?>
edited as per OP request...

Related

Using PHP Order By to sort query results

The below code displays data from a table and then filters it depending on the results of two combo boxes. I am able to order the results by ID once the form is submitted, but not on initial load (where all are listed). I have tried $sql = "SELECT * FROM Places ORDER BY ID"; which works when the list loads but returns an error when the form is submitted. Hope that makes sense. Any ideas? Thanks!
// Default query
$sql = "SELECT * FROM Places";
// check if form was submitted
if (isset($_POST['area'])) {
$connector = 'where';
if ($_POST['area'] != 'All') {
$sql .= " where Area = '".$_POST['area']."' ORDER BY ID";
$connector = 'and';
}
if ($_POST['theme'] != 'All') {
$sql .= " $connector Theme = '".$_POST['theme']."' OR Theme2 = '".$_POST['theme']."'
ORDER BY ID";
}
}
Your ORDER BY ID clause must appear at the very end of your statement. If both $_POST['area'] and $_POST['theme'] are filled, you end up with a query like this:
SELECT ... WHERE Area = 'some area' ORDER BY ID AND Theme = 'some theme'
Add the ORDER BY bit as the last part of your query.
I think you are missing a default behavior statement. I.e. Your IF statement doesn't have an else clause. So you are checking for isset and if it is change the select query, but there is nothing to say IF ! isset SELECT query should be .... ORDER BY ID.
Also I would try echoing your SQL queries out each time you set / change a portion of it to understand exactly what is being sent to the DB.
Lastly I always check the mysql.general_log table for the last run queries to see what is actually happening at the DB end.
It looks like it is possible for $_POST['area'] != 'All' and $_POST['theme'] != 'All'. In that case you will be putting the ORDER BY clause in twice. That probably your problem.
So try this.
// Default query
$sql = "SELECT * FROM Places";
// check if form was submitted
if (isset($_POST['area'])) {
$connector = 'where';
if ($_POST['area'] != 'All') {
$sql .= " where Area = '".$_POST['area']."'";
$connector = 'and';
}
if ($_POST['theme'] != 'All') {
$sql .= " $connector Theme = '".$_POST['theme']."' OR Theme2 = '".$_POST['theme'] . "'";
}
if ( $_POST['area'] != 'All' || $_POST['theme'] != 'All' ) {
$sql .= ' ORDER BY ID';
}
}
Thanks for all your help, I have solved the problem at the server end anyway so no need for code. Thanks for bringing attention to the security issues, I had these in the back of my mind but wasn't sure how bad it was! If I change the code to PDO would it help greatly? I have already reduced the privileges of the user to minimal. Thanks again.

PHP MYSQL syntax

I'm having a little trouble with my MYSQL query
I have a DB full of products and I have a dropdown menu which lets a user select what time of day they'd like to get get results for :-
Dropdown
Breakfast
Lunch
Evening
Anytime
At the moment my statement is
SELECT * from DEALS WHERE timeofday='post data from form';
Now this works fine, but with the option for 'Anytime' I'd like the query to be able to search for results of all/any of the above.
I was thinking of perhaps doing an IF statement which fires off 2 separate queries, one which says if the $_POST['timeofday'] == 'Anytime' then fire off
SELECT * from DEALS where timeofday='Breakfast'
OR timeofday='Lunch' OR timeofday='Evening';
otherwise just do the normal query, although wondered if it was possible to do this in just one statement.
Kind regards
$query = 'SELECT * from DEALS';
if ($_POST['timeofday'] != 'Anytime') {
$query .= ' WHERE timeofday="' . $_POST['timeofday'] . '"';
}
As DCoder mentioned, this approach is vulnerable to sql injection... You should check/sanitize the input or use prepared statements. In this case where there is a predefined set of values you can:
$knownTimesOfDay = array('Breakfast', 'Lunch', 'Evening', 'Anytime');
if (!in_array($_POST['timeofday'])) {
die('Unsuppotred time of day... Did it really come from the form?');
}
$query = 'SELECT * from DEALS';
if ($_POST['timeofday'] != 'Anytime') {
$query .= ' WHERE timeofday="' . $_POST['timeofday'] . '"';
}
Don't think it can be done in one statement.
You are going to have to use an if statement anyhow.
if these are the only 3 possible values for timeofday,then you can have an if in the php script like this:
if($_POST['timeofday'] != 'Anytime' )
sql .= "where timeofday='".$_POST['timeofday']."'";
This could turn out to be negative depending on the items you have in the table, but you could use:
SELECT * from DEALS where timeofday LIKE '%{$post_data}%'
It would return all the results from timeofday if $post_data was an empty string.

PHP/MYSQL advanced search script. How?

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.

MySQL where clause equals anything (SELECT * WHERE col = ANY_VALUE)

I'd like to create a query in MySQL that has an optional value. When the value is specified the query is filtered by that value, when the value is not all rows are returned. Here's the idea:
public function doQuery($item = 'ANY_VALUE') {
$query = "SELECT * FROM table WHERE item = ?";
db->fetchAll($query,array($item))
...
}
doQuery(); // Returns everything
doQuery($item='item1'); // Returns only rows where item = 'item1'
Is there an easy way to do this without creating two query strings depending on the value of $item?
As far as I know, no such "any" placeholder exists.
If you can use LIKE, you could do
SELECT * FROM table WHERE item LIKE '%'
if you can append a condition, you could nullify the item clause like this:
SELECT * FROM table WHERE item = ? OR 1=1
(won't work in your example though, because you are passing "item" as a parameter)
That's all the options I can see - it's probably easiest to work with two queries, removing the WHERE clause altogether in the second one.
This would probably work, but I*m not sure whether it's a good idea from a database point of view.
public function doQuery($item = 'ANY_VALUE') {
$query = "SELECT * FROM table WHERE item = ? OR 1 = ?";
db->fetchAll($query,array($item, ($item == 'ANY_VALUE' ? 1 : 0))
...
}
Better way to do this is first generate sql query from the parameter you need to bother on, and then execute.
function doQuery($params) {
$query = 'SELECT * FROM mytable ';
if (is_array($params) // or whatever your condition ) {
$query .= 'WHERE item = ' . $params[0];
}
$query .= ' ;';
// execute generated query
execute($query);
}
You cannot get distinct results without giving distinct query strings.
Using $q = "... WHERE item = '$item'" you DO create distinct query strings depending on the value of $item, so it is not that different from using
$q = "..." . ($item=='ANY_VALUE' ? something : s_th_else);.
That said I see two or three options:
use function doQuery($item = "%") { $query = "SELECT ... WHERE item LIKE '$item'"; ...}
But then callers to that function must know that they must escape a '%' or '_' character properly if they want to search for an item having this character literally (e.g. for item = "5% alcoholic solution", giving this as argument would also find "50-50 sunflower and olive oil non alcoholic solution".
use function doQuery($item = NULL) { $query = "SELECT ..."; if ($item !== NULL) $query .= " WHERE item = '$item' "; ...} (where I use NULL to allow any other string or numerical value as a valid "non-empty" argument; in case you also want to allow to search for NULL (without quotes) you must choose another "impossible" default value, e.g., [], and you must anyway use a distinct query without the single quotes which however are very important in the general case), or even:
use function doQuery($item = NULL) { if($item === NULL) $query = "SELECT ..."; else $query = "SELECT ... WHERE item = '$item' "; ...}, which is more to type but probably faster since it will avoid an additional string manipulation (concatenation of the first and second part).
I think the 2nd & 3rd options are better than the first one. You should explain why you want to avoid these better solutions.
PS: always take care of not forgetting the quotes in the SQL, and even to properly escape any special characters (quotes, ...) in arguments which can depend on user input, as to avoid SQL injections. You may be keen on finding shortest possible solutions (as I am), but neglecting such aspects is a no-no: it's not a valid solution, so it's not the shortest solution!

What is the best method for sorting columns with PhP and MySQL?

I would like to know which is the best way to sort table columns with PHP and MySQL. Is there a way to do this without having to set a variables like the following?
$strASC = $_GET["order"];
if ($strASC == "ASC")
{
$strASC = "DESC";
}
or does exist an SQL query that reverses the ASC or DESC depending on current status?
When you get a result set from a database it is in the order you specify. The database does not reorder the data in it's tables so therefore it does not know which "status" it is currently in.
Also watch out for SQL Injection in your example.
There's no function in particular for flipping the sort order, but you could do something like this:
$sortDir = $_GET['order'] == 'ASC' ? 'DESC' : 'ASC';
mysql_query('SELECT * FROM table ORDER BY col ' . $sortDir);
You're having a $_GET in that code so I assume that you want to use url params to set the order direction of your query.
Your code looks a bit confusing, you're setting $strASC to "DESC" which is a little bit of a contradiction ;)
What about something like that:
$sortDirection = $_GET['order'];
if ($sortDirection == 'ASC' || $sortDirection == 'DESC')
{
$sql = "SELECT mystuff FROM mytable WHERE mycrit ORDER BY " . $sortDirection;
}
else
{
echo 'Invalid sort direction';
}
no mysql doesnt do it automatically.
u can reduce it though
$strASC = $_GET['order']=='ASC'?'DESC':'ASC';
Using only PHP and the database, I do not think there is a better way that you could do that.
But, if you wanted to try using javascript and not running another query, you could take a look at jquery and tablesorter.

Categories