Robert Robert - 8 months ago 79
HTML Question

HTML TABLE PHP MySQL toggle MySQL sorting order ASC DESC on column header click

EDIT: added solution from the accepted answer

The hint I'm asking here is the smartest method for.

Need to be said first: I kindly ask you to avoid suggesting databales and similar.

I'm displaying a MySQL table content in a HTML table.

I have the view that is

showdbtable.php
which uses as include
echohtmltable.php
which queries the database and echoes the table rows.

So in
echohtmltable.php
currently there is quite everything involved in this question

GET variable check

if(isset($_GET['sortby'])){
$sortby=$_GET['sortby'];
$_GET['sortby']=''; }
else {
$sortby="id_ord"; }


and the consequent query

$query = "
SELECT id_ord, fornitore, negozio, data_insord, data_prevcons
FROM tesord
ORDER BY ".$sortby." DESC
LIMIT :from_record_num, :records_per_page";


which next is used to echo the table rows creating also the sort mechanism in the columns headers

echo "<th>".'<a href="showdbtable.php?sortby=fornitore">' . "Fornitore</th>";
echo "<th>".'<a href="showdbtable.php?sortby=negozio">' . "Negozio</th>";
echo "<th>".'<a href="showdbtable.php?sortby=data_insord">' . "Data_insord</th>";
echo "<th>".'<a href="showdbtable.php?sortby=data_prevcons">' . "Data_prevcons</th>";


as you know this first part works.

When I click one of the above links, the query works but currently as obvious from the code, in DESC only.

The kind request is a suggestion altogether. But PLEASE also NOTE that I have pagination, you see,
LIMIT :from_record_num, :records_per_page
, that should be taken in consideration.

Which is the smartest and efficient way to toggle between ASC and DESC in such a way that after having clicked one link, e.g. "Negozio", clicking again "Negozio" it goes sorted in ASC, and next click it will toggle DESC, and next click ASC and so on.

I'm sure the query will mutate in having a variable I may call $ascdesc

$query = "
SELECT id_ord, fornitore, negozio, data_insord, data_prevcons
FROM tesord
ORDER BY " . $sortby . " " . $ascdesc . "
LIMIT :from_record_num, :records_per_page";


need to manage if currently is ASC or DESC and toggle.

Thank you for hinting on some efficient and smart method to achieve the goal.



Solution: thank you to Rudy

For the sake of helping others newbies like me, here is how I have applied the solution

// function used in the links
function invdir($dir){ return ($dir == "DESC")? "ASC" : "DESC"; }

// collect, sanitize and default $_GET variables
// $ordinaper is the Italian of $sortby
$ordinaper = (isset($_GET['ordinaper']))? (filter_var($_GET["ordinaper"], FILTER_SANITIZE_STRING)) : "id_ord";
$ascdesc = (isset($_GET['ascdesc']))? (filter_var($_GET["ascdesc"], FILTER_SANITIZE_STRING)) : "DESC";
// $filtraforn is a filter/search to show only one provider, see the query, it is assigned with a ├Čn AJAX live search
$filtraforn = (isset($_GET['filtraforn']))? (filter_var($_GET["filtraforn"], FILTER_SANITIZE_STRING)) : "";

// build the common URL GET part
$getlinks = "&filtraforn=".$filtraforn."&page=".$page."&ascdesc=";
// the variable $page comes from the pagination which is out of the scope. Here I was dealing with the correct management of sorting the HTML table columns

// the query is built accordingly, later is used in a PDO statement
$query = "SELECT id_ord, fornitore, negozio, data_insord, data_prevcons FROM tesord ";
$filtro = (strlen($filtraforn))? "WHERE fornitore = '" . $filtraforn . "' " : "";
$query = $query . $filtro . "ORDER BY ". $ordinaper ." ". $ascdesc ." LIMIT :from_record_num, :records_per_page";
// LIMIT :from_record_num, :records_per_page are bound later with variables coming from the pagination which is out of the scope. Here I was dealing with the correct management of sorting the HTML table columns

// and here it is the final table heading
// the ternary operator (($ordinaper!=="id_ord")? "DESC" : invdir($ascdesc)) is used because when clicking a different column, I want to default the sorting in DESC
echo "<tr>";
echo "<th></th>";
echo "<th>". '<a href="read.php?ordinaper=id_ord' .$getlinks. (($ordinaper!=="id_ord")? "DESC" : invdir($ascdesc)) .'">' . "id_ord</th>";
echo "<th>". '<a href="read.php?ordinaper=ord_evaso' .$getlinks. (($ordinaper!=="ord_evaso")? "DESC" : invdir($ascdesc)) .'">' . "Stato</th>";
echo "<th>". '<a href="read.php?ordinaper=fornitore' .$getlinks. (($ordinaper!=="fornitore")? "DESC" : invdir($ascdesc)) .'">' . "Fornitore</th>";
echo "<th>". '<a href="read.php?ordinaper=negozio' .$getlinks. (($ordinaper!=="negozio")? "DESC" : invdir($ascdesc)) .'">' . "Negozio</th>";
echo "<th>". '<a href="read.php?ordinaper=data_insord' .$getlinks. (($ordinaper!=="data_insord")? "DESC" : invdir($ascdesc)) .'">' . "Data_insord</th>";
echo "<th>". '<a href="read.php?ordinaper=data_prevcons' .$getlinks. (($ordinaper!=="data_prevcons")? "DESC" : invdir($ascdesc)) .'">' . "Data_prevcons</th>";
echo "<th>Paia Inev.</th>";
echo "<th>Azione</th>";
echo "</tr>";

Answer Source

If you are already sending the sortby via GET, why wouldn't you send the ASC,DESC Option too, I mean, you could use 1 and 0 instead of the actual ASC/DESC and toggle it inside your code,for example:

$ascdesc = ($_GET['ad'])? '0' : '1';

And just add the var to the link

echo "<th>".'<a href="showdbtable.php?sortby=negozio&ad='.$ascdesc.'">' . "Negozio</th>";

And in you query, something like

 $ascdesc = ($_GET['ad'])? 'asc' : 'desc';

Something very important here is that if you are accepting user input via GET, you have to sanitize the var to avoid SQL injections, don't forget this.

UPDATE:

Possible implementation with your own code:

$sortby = (isset($_GET['sortby']))? $_GET['sortby'] : "id_ord";
$ascdesc = ($_GET['ad']=='asc')? 'ASC' : 'DESC';

The Query:

$query = "SELECT id_ord, fornitore, negozio, data_insord, data_prevcons 
          FROM tesord 
          ORDER BY ".$sortby." ".$ascdesc." 
          LIMIT :from_record_num, :records_per_page";

The link:

echo "<th>".'<a href="showdbtable.php?sortby=fornitore&ad=<?=(($_GET['ad']=='asc')? 'desc' : 'asc';)?>">' . "Fornitore</th>";

And if you need to add the page, just add the current page and change sort, you can add a var also to the link

echo "<th>".'<a href="showdbtable.php?sortby=fornitore&ad=<?php echo (($_GET['ad']=='asc')? 'desc' : 'asc';)?>&page=<?php echo $_GET['page]?>">' . "Fornitore</th>";

There are many other ways to handle the pagination and sorting, but I think that, without getting into a lot of trouble, this could be a way, however, about the security, you can use mysql_real_escape

You could also leave everything to javascript/jQuery by implementing something like this

Hope this can give you a better understanding, happy coding.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download