This is a document written using ReMarkable, a shorthand syntax for generating HTML.
{ "date" : 200906071513,
"updated" : 200906071513,
"licence" : "cc-by",
"tags" : ["web-dev"]
}
<section>
# Sorting a Directory Listing Folders First, Then By File Type, Then By Name in PHP #
*Something I think might be useful to people.* This code takes a directory listing and then sorts the contents listing folders first (in alphabetical order), then the files are sorted by file type and then alphabetically for each file type.
~~~ PHP ~~~>
//directory to list, you choose; here we’ll just use the webroot
$path = $_SERVER['DOCUMENT_ROOT'];
//warning: `is_dir` will need you to change to the parent directory of what you are testing
//see <uk3.php.net/manual/en/function.is-dir.php#70005> for details
chdir ($path);
//get a directory listing
$dir = array_diff (scandir ('.'),
//folders / files to ignore
array ('.', '..', '.DS_Store', 'Thumbs.db')
);
//sort folders first, then by type, then alphabetically
usort ($dir, create_function ('$a,$b', '
return is_dir ($a)
? (is_dir ($b) ? strnatcasecmp ($a, $b) : -1)
: (is_dir ($b) ? 1 : (
strcasecmp (pathinfo ($a, PATHINFO_EXTENSION), pathinfo ($b, PATHINFO_EXTENSION)) == 0
? strnatcasecmp ($a, $b)
: strcasecmp (pathinfo ($a, PATHINFO_EXTENSION), pathinfo ($b, PATHINFO_EXTENSION))
))
;
'));
//echo to screen
header ('content-type: text/plain');
print_r ($dir);
<~~~
Here’s how this breaks down:
<``usort`` (//uk3.php.net/manual/en/function.usort.php)> sorts an array using another function given two items to compare. Return “-1” if the first should go above the other, 1 if the second should go above the other and 0 if they are equal.
We create a function with ``$a`` and ``$b`` parameters corresponding to the two items being compared for sorting as it goes through the list.
~~~ PHP ~~~>
return is_dir ($a)
<~~~
If the first item is a directory then…
~~~ PHP ~~~>
? (is_dir ($b) ? strnatcasecmp ($a, $b) : -1)
<~~~
Check if the second item is a directory. If both items are directories then compare them by name. <``strnatcasecmp`` (//uk2.php.net/manual/en/function.strnatcasecmp.php)> will return “-1”, “0” or “1” accordingly.
~~~ PHP ~~~>
: (is_dir ($b) ? 1 : (
<~~~
Now if the first item is not a directory, check if the second item is. If the second item is a directory, it will go above the first item—return “1”.
¬¬
Else, compare file extensions
~~~ PHP ~~~>
strcasecmp (pathinfo ($a, PATHINFO_EXTENSION), pathinfo ($b, PATHINFO_EXTENSION)) == 0
<~~~
If the file extensions are equal then compare the file names
~~~ PHP ~~~>
? strnatcasecmp ($a, $b)
<~~~
Finally, if the file extensions are not equal, compare them again, this time returning the result
~~~ PHP ~~~>
: strcasecmp (pathinfo ($a, PATHINFO_EXTENSION), pathinfo ($b, PATHINFO_EXTENSION))
<~~~
And that’s it!
¬¬
Enjoy.
</section>