在PHP中按日期排序文件

sas*_*ori 53 php sorting

我目前有一个index.php文件,它允许我输出同一目录中的文件列表,输出显示名称然后我使用filemtime()函数来显示文件被修改的日期.我现在的问题是,如何对输出进行排序以显示最新修改的文​​件?我一直在考虑如何做到这一点.如果我只是用mysql交互来做这件事就没问题了.请给我一个例子,说明如何从最新修改的文​​件开始排序和输出文件列表.这就是我现在所拥有的

if ($handle = opendir('.')) {
while (false !== ($file = readdir($handle))) {
       if ($file != "." && $file != "..") {
        $lastModified = date('F d Y, H:i:s',filemtime($file));
          if(strlen($file)-strpos($file,".swf")== 4){
            echo "<tr><td><input type=\"checkbox\" name=\"box[]\"></td><td><a href=\"$file\" target=\"_blank\">$file</a></td><td>$lastModified</td></tr>";
           }
       }
   }
   closedir($handle);
}
Run Code Online (Sandbox Code Playgroud)

Gor*_*don 159

这会将带有.swf扩展名的path/to/files中的所有文件放入一个数组中,然后按文件的mtime对该数组进行排序

$files = glob('path/to/files/*.swf');
usort($files, function($a, $b) {
    return filemtime($a) < filemtime($b);
});
Run Code Online (Sandbox Code Playgroud)

以上使用Lambda函数,需要PHP 5.3.在5.3之前,你会这样做

usort($files, create_function('$a,$b', 'return filemtime($a)<filemtime($b);'));
Run Code Online (Sandbox Code Playgroud)

如果您不想使用匿名函数,您也可以将回调定义为常规函数,并将函数名称传递给它usort.

使用生成的数组,然后迭代文件,如下所示:

foreach($files as $file){
    printf('<tr><td><input type="checkbox" name="box[]"></td>
            <td><a href="%1$s" target="_blank">%1$s</a></td>
            <td>%2$s</td></tr>', 
            $file, // or basename($file) for just the filename w\out path
            date('F d Y, H:i:s', filemtime($file)));
}
Run Code Online (Sandbox Code Playgroud)

请注意,因为您filemtime在排序文件时已经调用过,所以由于stat缓存而在foreach循环中再次调用它时没有额外的成本.

  • @elias没有冒犯,但我觉得因为你给出的理由而对一个完全有效的答案进行投票是相当荒谬的.谈论可读性,您的代码需要花费更长的时间来解决问题.我称之为Spaghetti代码.而且,如果你对于使用PHP的bugtracker提出申诉感到不满意. (37认同)
  • 值得注意的是,上面的Lambda函数首先使用最年轻的文件(即日期升序)进行排序.如果你想要最早的文件,只需切换```````. (4认同)
  • -1你没有使用他的代码,而usort是在这种情况下使用的最差的排序函数.但地狱,所有人都投票给你,因为它看起来很花哨.* - * (2认同)
  • @IfediOkonkwo我不知道有什么特别的问题,但是有些人不喜欢`usort`,因为通过闭包进行排序会增加一些内部函数调用开销,例如,它比其他类型慢。在实践中,您想在得出结论之前先介绍一下测试。在大多数情况下,间接费用不会产生相关影响。 (2认同)

eli*_*ias 19

您需要将文件放入数组中,以便对最后修改的文件进行排序和查找.

$files = array();
if ($handle = opendir('.')) {
    while (false !== ($file = readdir($handle))) {
        if ($file != "." && $file != "..") {
           $files[filemtime($file)] = $file;
        }
    }
    closedir($handle);

    // sort
    ksort($files);
    // find the last modification
    $reallyLastModified = end($files);

    foreach($files as $file) {
        $lastModified = date('F d Y, H:i:s',filemtime($file));
        if(strlen($file)-strpos($file,".swf")== 4){
           if ($file == $reallyLastModified) {
             // do stuff for the real last modified file
           }
           echo "<tr><td><input type=\"checkbox\" name=\"box[]\"></td><td><a href=\"$file\" target=\"_blank\">$file</a></td><td>$lastModified</td></tr>";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

没有经过测试,但这是怎么做的.

  • @sasori请注意,当您拥有相同mtime的文件时,此解决方案将无法正常工作,因为它将覆盖该mtime的先前文件名. (19认同)
  • 完全是戈登,我希望有一种方法可以让BUMP评论更加明显,因为我花了一个小时来挖掘错误.显然,上面代码背后的想法是正确的,但这个错误使它绝对没用. (3认同)
  • 要更正此答案,您可以将文件路径用作数组键,将日期用作值,这样就不会有重复的键。如果我理解得很好,要在不更改键的情况下对值进行排序,您必须使用 asort ()。 (3认同)
  • 我唯一要做的更改是:`$ filetime = filemtime(“ $ path / $ file”);``while(isset($ files [$ filetime])){$ filetime ++; }`$ files [$ filetime] = $ file;` (2认同)

Dan*_*jel 10

使用RecursiveDirectoryIterator类的示例,它是一种在文件系统上递归迭代的便捷方式.

$output = array();
foreach( new RecursiveIteratorIterator( 
    new RecursiveDirectoryIterator( 'path', FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS ) ) as $value ) {      
        if ( $value->isFile() ) {
            $output[] = array( $value->getMTime(), $value->getRealPath() );
        }
}

usort ( $output, function( $a, $b ) {
    return $a[0] > $b[0];
});
Run Code Online (Sandbox Code Playgroud)

  • 人们需要在 PHP 中采用 OOP 方法,以使其与其他语言相比具有竞争力。 (2认同)
  • @RaheelKhan为什么?当它更容易解决问题时使用OOP,当它更复杂时不要使用OOP.OOP不会使任何更好的东西,也不会是你的代码或语言.它只是允许某些问题更有效地解决(我认为这不是这里的情况). (2认同)
  • 虽然您实际上并不需要使用“RecursiveDirectoryIterator”来解决这个问题(特别是如果您不想要递归结果),但这是这里使用“usort”与任何类型的缓存的唯一答案。戈登的回答在这里有如此大的吸引力,有点令人震惊;您绝对不想在比较器函数内进行文件系统查找。由于文件系统查找,“filemtime”的成本很高,所以如果我必须这样做,我宁愿每个文件执行一次(就像在这个答案中)而不是数千次。更不用说,“DirectoryIterator::getMTim​​e”一开始就很高效。 (2认同)