/    Sign up×
Community /Pin to ProfileBookmark

[RESOLVED] PHP Sortable table ASC AND DESC (NOT javascrript AND NO (My)SQL)

Somebody recommended me to ask it at NoggDog … but of course any good solution of somebody else is fine
I’m making a directory listing of an homepage with 3 columns : file name – time – size
Now I want to make the columns sortable – ascending AND descending – in PHP (NOT javascript!!)
But I don’t get it to work (only one way works)
But I want it to work from ASC to DESC and visa versa.
Can you help me out please and make changes to the code below so it works (td header click asc and td header click desc for all three columns )??

Code so far

[code=php]<?php
error_reporting(0);
@ini_set(‘display_errors’, 0);

$dir = “*”;
$read_dir = glob($dir);

function sort_name($a,$b) {
return glob($a) < glob($b);
}
function sort_size($a,$b) {
return filesize($a) < filesize($b);
}
function sort_time($a,$b) {
return filemtime($a) < filemtime($b);
}

if($_GET[‘sort’]==’size’) {
usort($read_dir, “sort_size”);
}
elseif($_GET[‘sort’]==’time’) {
usort($read_dir, “sort_time”);
}
else {
sort($read_dir, “sort_name”);
}

echo “<table border=’1′>”;
echo “<tr>”;
echo “<td><a href=?sort=name>Name</a></td>”;
echo “<td><a href=?sort=size>Size</a></td>”;
echo “<td><a href=?sort=time>Time</a></td>”;
echo “</tr>”;

foreach ($read_dir as $files) {
echo “<tr>”;
echo “<td style=’width:300px;’>” . $files . “</td>”;
echo “<td style=’width:170px;text-align:center;’>” . date(“d.m.Y H:i:s”, filemtime($files)) . “</td>”;
echo “<td style=’width:80px;text-align:right;’>” .filesize($files) . ” B</td>”;
echo “</tr>”;
}
echo “</table>”;
?> [/code]

Kind regards

to post a comment
PHP

21 Comments(s)

Copy linkTweet thisAlerts:
@ginerjmAug 01.2017 — Stop using @

Turn on error checking until you get this working.

Which one of these DOES work? (Probably the default of order by filename since you're not using usort correctly).

Try dumping the contents of $read_dir to see what you have to work with.
Copy linkTweet thisAlerts:
@coderunnerauthorAug 01.2017 — Thank you for replying.

When I change usort in sort or sort in usort it works (one direction) but I want both asc and desc in "one"(?) so the script works in both directions

Yes it gives me 3 errors when I add the error checking ?

[I]Notice: Undefined index: sort in /***/index.php on line 20

Notice: Undefined index: sort in /*
**
/index.php on line 23

Warning: sort() expects parameter 2 to be integer, string given in /***/index.php on line 27[/I]


but I don't know what to do now ...

Is it possible to give me the working code (or somebody else) cause I'm a newbie with PHP and trying to let it work for weeks now.

Thanks in advance for helping me

Kind regards
Copy linkTweet thisAlerts:
@ginerjmAug 01.2017 — Have you made the errors go away? If you are using an index that doesn't exist you have to think about what your array must look like. Do a var_dump on it to see what indices it has.

Look up the 'sort()' function in the manual for the last error.

If you are newbie at this then you need to do some learning before you embark on more complex tasks. We don't Write code here for others; we Help them With their coding attempts.

Did you do ALL of the things that I suggested?
Copy linkTweet thisAlerts:
@coderunnerauthorAug 01.2017 — No more errors but now it works only descending so now the code for ascending ... so it works in both directions

[code=php]<?php
//error_reporting(0);
//@ini_set('display_errors', 0);
error_reporting(E_ALL);
ini_set('display_errors', '1');

$dir = "*";
$read_dir = glob($dir);

$sort = "";

if(isset($_GET['sort'])){
$sort = $_GET['sort'];
}
function sort_name($a,$b) {
return glob($a) < glob($b);
}
function sort_time($a,$b) {
return filemtime($a) < filemtime($b);
}
function sort_size($a,$b) {
return filesize($a) < filesize($b);
}

if($sort=='size') {
usort($read_dir, "sort_size");
}
elseif($sort=='time') {
usort($read_dir, "sort_time");
}
else {
usort($read_dir, "sort_name");
}

echo "<table border='1'>";
echo "<tr>";
echo "<td><a href=?sort=name>Name</a></td>";
echo "<td><a href=?sort=size>Size</a></td>";
echo "<td><a href=?sort=time>Time</a></td>";
echo "</tr>";


foreach ($read_dir as $files) {
echo "<tr>";
echo "<td style='width:300px;'>" . $files . "</td>";
echo "<td style='width:80px;text-align:right;'>" .filesize($files) . " B</td>";
echo "<td style='width:170px;text-align:center;'>" . date("d.m.Y H:i:s", filemtime($files)) . "</td>";
echo "</tr>";
}
echo "</table>";
?>
[/code]
Copy linkTweet thisAlerts:
@ginerjmAug 01.2017 — try reading the manual for usort. You need to return one of 3 values, not two

PS - your sort for the 'name' choice is just plain silly. You are comparing two glob results? Again - if you READ the manual for glob you would see how it works.
Copy linkTweet thisAlerts:
@coderunnerauthorAug 01.2017 — I don't get it and see no difference in my usort ... sorry ... [url=https://www.w3schools.com/php/showphp.asp?filename=demo_func_usort][COLOR="#0000CD"]usort example[/COLOR][/url]
[code=php]<!DOCTYPE html>
<html>
<body>

<?php
function my_sort($a,$b)
{
if ($a==$b) return 0;
return ($a<$b)?-1:1;
}

$a=array(4,2,8,6);
usort($a,"my_sort");

$arrlength=count($a);
for($x=0;$x<$arrlength;$x++)
{
echo $a[$x];
echo "<br>";
}

?>

</body>
</html>[/code]

[code=php]usort($a,"my_sort");[/code]
mine
[code=php]usort($read_dir, "sort_size"); [/code]
Copy linkTweet thisAlerts:
@NogDogAug 01.2017 — I'll have some thoughts tonight (if I remember), but no time now to post them. (It's not a quick, simple, "just change X.")
Copy linkTweet thisAlerts:
@coderunnerauthorAug 01.2017 — I'll have some thoughts tonight (if I remember), but no time now to post them. (It's not a quick, simple, "just change X.")[/QUOTE]
Hey NogDog,

I am very happy you are willing to help me.

I didn't know it is so difficult. Then I think I wouldn't have found it at all.

Okay I'll wait and let you think about my problem, I hope you'll find a solution soon ?

Thank you very much and looking forwards to your answer ...

Best regards
Copy linkTweet thisAlerts:
@ginerjmAug 01.2017 — At least your new usort callback function is correct now.
Copy linkTweet thisAlerts:
@NogDogAug 02.2017 — Well, I ended up having some fun(?) with this. There's no defensive coding, and you could possibly enhance it to ignore '.' and '..', and perhaps any file name starting with a dot? I'll just throw it out here, let you digest it, then ask questions about anything you don't understand (after you look up the function first on php.net ? ).

Dir.php:
[code=php]
<?php

class Dir
{
private $data = array();
private $sortField = 'name';
private $direction = 1;

public function __construct($path)
{
$handle = opendir($path);
while($data = readdir($handle)) {
$this->data[]['name'] = $data;
}
foreach($this->data as $ix => $data) {
$this->data[$ix]['size'] = filesize($data['name']);
$this->data[$ix]['timestamp'] = date(
'Y-m-d H:i:s',
filemtime($data['name']
));
}
}

public function sortByName($asc = true)
{
$this->sortBy('name', $asc);
}

public function sortByTime($asc=true)
{
$this->sortBy('timestamp', $asc);
}

public function sortBySize($asc=true)
{
$this->sortBy('size', $asc);
}

private function sortBy($field, $asc=true)
{
$this->sortField = $field;
$this->direction = $asc ? 1 : -1;
usort($this->data, array($this, 'sort'));
}

private function sort($a, $b) {
return strnatcasecmp(
$a[$this->sortField],
$b[$this->sortField]
) * $this->direction;
}

public function data()
{
return $this->data;
}
}
[/code]


Sample usage:
[code=php]
<?php
require_once 'Dir.php';

date_default_timezone_set('America/New_York'); // if not set in your PHP config, set to what you want
$dir = new Dir('/users/creace/Projects'); // set to desired actual directory path
$dir->sortByTime(false); // descending
$data = $dir->data();
echo "<table>n<tr><th>Name</th><th>Size</th><th>Date</th></tr>n";
foreach($data as $row) {
echo "<tr><td>{$row['name']}</td><td>{$row['size']}</td><td>{$row['timestamp']}</td></tr>n";
}
echo "</table>n";
[/code]
Copy linkTweet thisAlerts:
@coderunnerauthorAug 02.2017 — Hello NogDog,

I "played around" with your code and tried to understand what you wrote. It looks great but I have a feeling some code is missing because the headers <th> are not clickable and not changing the order.

Isn't there a code missing in the "Sample usage?HP" ?

Thank you very much for helping me here ?

Best regards
Copy linkTweet thisAlerts:
@NogDogAug 02.2017 — I just concentrated on the PHP directory object. I figured how it's actually implemented in HTML/JavaScript is a separate issue for those who like writing client-side code. ?
Copy linkTweet thisAlerts:
@coderunnerauthorAug 02.2017 — Hi NogDog,

So if I understand you well, it can't be done in PHP only and it needs to be done with extra javascript? ? Weird because in my example - see higher in this tread - it can do it in one way (usort) with clicking on header with no javacript, so pure PHP.

And that was my question so it works in both directions sorting ASC and DESC on all 3 columns with header<th> click.

I already made the javascript version with sorting ASC and DESC on all columns in both directions but I wanted it to be done with PHP ONLY so NO javascript.

I know it can be done with a (MY)SQL database but this isn't a (MY)SQL ... only a directory listing.

Best regards
Copy linkTweet thisAlerts:
@NogDogAug 02.2017 — No, it could just be HTML/PHP, where each column header would be a link with some query params to tell PHP how you want to sort the table -- so you'd need some PHP logic to figure out if it should be an ascending or descending parameter. A JavaScript solution would probably be more responsive, as it could just sort it locally in the browser and would not have to send a new page request to the web server -- and there's probably a JQuery method you could use to add column-based sorting quite easily, I suspect. For that matter, there's probably a PHP-based class/function/package out there that could help implement what you're describing. If you roll your own in HTML/PHP, then you need to add <a> tags with the necessary links to each table header (or maybe to a couple down and up arrow icons?) with the necessary info, something like
[code=html]
<th>Name <a href='?column=name&direction=asc><img src='/img/uparrow.png'></a> <a href='?column=name&direction=desc><img src='/img/downarrow.png'></a><th>
[/code]


Then in ypur PHP code, you'd look for $_GET['column'] and $_GET['direction'] (or whatever you prefer to call them), and based on those values, decide which sort method to call in the Dir class and whether or not the ascending flag is true or false.
Copy linkTweet thisAlerts:
@coderunnerauthorAug 02.2017 — Hello NoDog,

Now you confuse me ?

The a href link I understand .. I made it with ascii symbols
[code=php]<th><a href='?column=name&direction=asc'>&#x25B2;</a> Name <a href='?column=name&direction=desc'>&#x25BC;</a></th>[/code]

But the other explanation I don't understand ?

Is it possible to add (re-write) the code you said in Dir.php and the Sample usage PHP so I can see how it works the way you said.

You would do me a big favor and I would appreciate it very much ... thanks for your time!!

Best regards
Copy linkTweet thisAlerts:
@NogDogAug 02.2017 — I might do something like this (untested):
[code=php]
$dir = new Dir('/directory/to/sort');
$column = !empty($_GET['column']) ? $_GET['column'] : 'name';
$direction = (!empty($_GET['direction']) and $_GET['direction'] == 'desc') ? false : true;
switch($column) {
case 'size':
$dir->sortBySize($direction);
break;
case 'time':
$dir->sortByTime($direction);
break;
default:
$dir->sortByName($direction);
}
$data = $dir->data();
// now echo out the data in your table...
[/code]
Copy linkTweet thisAlerts:
@coderunnerauthorAug 02.2017 — Wow NogDog that's super ... it works like a charm ... you made my day pal ... thank you a million times

I wish I was as good as you in PHP! ?

Best regards
Copy linkTweet thisAlerts:
@NogDogAug 02.2017 — You can send your payment to...

?

(Wonder if I should put that class on GitHub....)
Copy linkTweet thisAlerts:
@coderunnerauthorAug 02.2017 — Good I listened to the guy who sent me to this forum and who recommended you.

He said you are an admin who is very responsive. And that's true what he said!

If you had put that class on GitHub or the internet earlier then I didn't have to bother you ... lol

But it's a great job you did and I really, really appreciate it!

Best regards
Copy linkTweet thisAlerts:
@coderunnerauthorAug 02.2017 — Good ... now I know where to find the class and usage but I already have it now ?
×

Success!

Help @coderunner spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.18,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...