9

I'm using DirectoryIterator to generate a linked-list of PDF files. (There's also some code to break up the file name to make the list more user friendly.) I'd like to sort the results by file name, but can't figure out how. I know I need to put the results into an array, and then sort the array. But, I can't find an example anywhere that does it quite like I am, so I can't figure out how to integrate the array/sort into my code, since my PHP is weak. Can anyone lend an assist?

($path is declared elsewhere on the page)

<?php
        if (is_dir($path))
          {
            print '<ul>';
            foreach (new DirectoryIterator($path) as $file)
              {
                if ($file->isDot()) continue;
                $fileName = $file->getFilename();
                $pieces = explode('.', $fileName);
                $date = explode('-', $pieces[2]);
                $filetypes = array(
                    "pdf",
                    "PDF"
                );
                $filetype = pathinfo($file, PATHINFO_EXTENSION);
                if (in_array(strtolower($filetype), $filetypes))
                  {
                    print '<li><a href="' . $path . '' . $fileName . '">' . $pieces[2] . '</a></li>';
                  }
              }
             print '</ul>';
          }
        else
          {
            print $namePreferred . ' are not ready.</p>';
          }

        ?>
Nathan
  • 766
  • 2
  • 9
  • 19
  • 1
    Please see this question http://stackoverflow.com/questions/1076881/after-using-files-new-directoryiterator-in-php-how-do-you-sort-the-items – Mihai Matei Aug 20 '13 at 14:10
  • @Matei Mihai I've seen that one, but the PHP logic is different and I can't figure out how to make it work for the code above. I'm also not sure what to use for a key in that example, the filename? – Nathan Aug 20 '13 at 14:12
  • @Nathan How is `$namePreferred` defined? – Funk Forty Niner Aug 20 '13 at 14:17
  • @Fred It's also defined earlier in the code. It comes from a MySQL database. – Nathan Aug 20 '13 at 14:26

2 Answers2

12

Placing your valid files into an array with various columns you can sort by is probably the best bet, an associate one at that too.

I used asort() "Sort an array and maintain index association" with I think best fits your requirements.

if (is_dir($path)) 
{
    $FoundFiles = [];

    foreach (new DirectoryIterator($path) as $file) 
    {

       if ($file->isDot())
       {
          continue;
       }
    
       $fileName = $file->getFilename();

       $pieces    = explode('.', $fileName);
       $date      = explode('-', $pieces[2]);
                
       $filetypes = [ "pdf", "PDF" ];
       $filetype  = pathinfo( $file, PATHINFO_EXTENSION );

       if ( in_array( strtolower( $filetype ), $filetypes )) 
       {
          /** 
           *  Place into an Array
          **/
          $foundFiles[] = array( 
              "fileName" => $fileName,
              "date"     => $date
          );       
       }
    }
 }

Before Sorting

print_r( $foundFiles );

Array
(
   [0] => Array
       (
            [fileName] => readme.pdf
            [date] => 22/01/23
       )

   [1] => Array
       (
            [fileName] => zibra.pdf
            [date] => 22/01/53
       )

    [2] => Array
       (
            [fileName] => animate.pdf
            [date] => 22/01/53
       ) 
)
   

        

After Sorting asort()

/** 
 *   Sort the Array by FileName (The first key)
 *   We'll be using asort()
**/ 
asort( $foundFiles );

/** 
 *   After Sorting 
**/ 
print_r( $foundFiles );

Array
(
    [2] => Array
        (
            [fileName] => animate.pdf
            [date] => 22/01/53
        )

    [0] => Array
        (
            [fileName] => readme.pdf
            [date] => 22/01/23
        )

    [1] => Array
        (
            [fileName] => zibra.pdf
            [date] => 22/01/53
        )
 )

Then for printing with HTML after the function completes - Your code did it whilst the code was in a loop, which meant you couldn't sort it after it's already been printed:

<ul>
   <?php foreach( $foundFiles as $file ): ?>
      <li>File: <?php echo $file["fileName"] ?> - Date Uploaded: <?php echo $file["date"]; ?></li>
   <?php endforeach; ?>
</ul>
MackieeE
  • 11,751
  • 4
  • 39
  • 56
  • 2
    Many thanks for explaining where I went wrong (printing inside the loop) and how to achieve my goal! – Nathan Aug 20 '13 at 15:33
3

Use scandir instead of DirectoryIterator to get a sorted list of files:

$path = "../images/";

foreach (scandir($path) as $file){

    if($file[0] == '.'){continue;}//hidden file

    if( is_file($path.$file) ){

    }else if( is_dir($path.$file) ){

    }
}

scandir is case sensitive. For case insensitive sorting, see this answer: How do you scan the directory case insensitive?

Jarir
  • 327
  • 3
  • 10