Сортировка файлов с помощью filemtime() и usort() дает случайные результаты

Я использую usort() и filemtime() для сортировки файлов по дате модификации, но они случайным образом возвращают файлы в неправильном порядке. Я думаю, мне не хватает чего-то очень простого, но я не могу понять, что.

usort($user_files, function($a, $b) {
    return filemtime($a) > filemtime($b);
});
foreach ($user_files as $f) {
    echo $f . "<br />";
}

После этого загружаю файл. Полный код.

При загрузке файлов 1.txt ... 10.txt для проверки того, что происходит, отображались следующие результаты:

6.txt
5.txt
4.txt
3.txt
2.txt
1.txt
7.txt Uploaded!

Как и ожидалось. Затем, когда я достиг 8.txt:

6.txt
7.txt
5.txt
4.txt
2.txt
3.txt
1.txt
8.txt Uploaded!

В другой раз все было нормально, пока я не дошел до 10.txt:

7.txt
8.txt
9.txt
6.txt
5.txt
2.txt
3.txt
4.txt
1.txt
10.txt Uploaded!

Пока ls -t вернулся:

10.txt  9.txt  8.txt  7.txt  6.txt  5.txt  4.txt  3.txt  2.txt  1.txt

Итак... Что там происходит?

Debian Wheezy 7.4, up-to-date.
PHP Version 5.4.4-14+deb7u8
Linux pc 3.2.0-4-amd64 #1 SMP Debian 3.2.54-2 x86_64
FPM/FastCGI
nginx/1.2.1

person Alex    schedule 11.04.2014    source источник
comment
Ваш код исчез из pastebin.   -  person Craig Trader    schedule 20.04.2014


Ответы (2)


Человек usort говорит http://www.php.net/manual/en/function.usort.php

value_compare_func

Функция сравнения должна возвращать целое число, меньшее, равное или большее нуля, если считается, что первый аргумент соответственно меньше, равен или больше второго.

Но предоставленный обратный вызов имеет только оператор «>»:

{
    return filemtime($a) > filemtime($b);
}

и Мужчина говорит (http://www.php.net/manual/en/language.operators.comparison.php), что оператор «Больше чем», также известный как >, возвращает только значение true или false, но не отрицательное/ноль/положительное число, как было запрошено.

$a > $b Больше, чем TRUE, если $a строго больше, чем $b.

Что вы думаете об использовании оператора «Вычитание» «-» между двумя filemtime, потому что Ман снова говорит, что filemtime — это целое число (http://www.php.net/manual/en/function.filemtime.php).

И где-то на этом сайте есть повторяющийся ответ (погуглил с помощью filemtime usort и чувствует себя удачливым - первый результат): Заказать этот массив по дате изменен? и ответ был предоставлен Майклом Берковски, который говорит:

  if (filemtime($a) === filemtime($b)) return 0;
  return filemtime($a) < filemtime($b) ? -1 : 1; 
person osgx    schedule 14.04.2014
comment
Спасибо! Но это не сработало. Как ни странно, теперь кажется, что порядок скремблируется всегда при загрузке 6-го файла. Я предполагаю, что проблема не связана с usort(), но я не могу понять, что именно. Я отредактировал вопрос с полным кодом. - person Alex; 14.04.2014
comment
+1, даже если это не был хороший ответ, это было хорошим предположением, поскольку некоторым угрозам может потребоваться меньше времени, чем 1 секунда, для обработки нескольких файлов. - person Alain Tiemblo; 16.04.2014

Я понял, в чем дело, и, как и ожидалось, это не имело никакого отношения к usort. Функция, используемая для получения файлов, получала только имена файлов, а не абсолютный путь к ним. Таким образом, filemtime вызывался с бессмысленной строкой. Я понятия не имею, почему php не выдает никаких предупреждений об этом.

person Alex    schedule 14.04.2014
comment
300 наград за простую ошибку пользователя :) Но предупреждения нет, потому что 2.txt — правильный путь. Он просто не смог найти файл и поэтому возвращает FALSE, так как произошел сбой. Также было довольно очевидно, что вы получили только имя файла. Поскольку ваш тест foreach работает с теми же данными, что и функция usort. - person Hugo Delsing; 14.04.2014