#php
#php
Вопрос:
Я ищу некоторую помощь в том, чтобы заставить это работать.
В корне у меня есть index.php файл (показан ниже), и у меня также есть 3 папки. Изображения случайным образом добавляются в эти папки, что я хочу сделать, так это в этих 3 столбцах таблицы отобразить (отсортировать) последние файлы в каждой папке с указанием даты их создания / изменения, или, в основном, даты их добавления.
Я добавил скриншот, чтобы показать, что у меня есть на данный момент, 3 столбца работают нормально, просматривая последние файлы в каждой папке. Однако под каждым изображением они, похоже, имеют одну и ту же дату изменения, что неверно.
Кто-нибудь может увидеть, где я ошибаюсь?
<?php
date_default_timezone_set('Europe/London');
$dirname = "dir1";
$dirnameTwo = "dir2";
$dirnameThree = "dir3";
$cam1 = scandir($dirname, 1);
$cam2 = scandir($dirnameTwo, 1);
$cam3 = scandir($dirnameThree, 1);
?>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<head>
<meta http-equiv='refresh' content='10'>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA 058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<meta http-equiv='cache-control' content='max-age=0' />
<meta http-equiv='cache-control' content='no-cache' />
<meta http-equiv='expires' content='0' />
<meta http-equiv='expires' content='Tue, 01 Jan 1980 1:00:00 GMT' />
<meta http-equiv='pragma' content='no-cache' />
</head>
<html>
<body>
<style type="text/css">
.pi-title {
padding: 1rem;
}
</style>
<div class="container">
<div class="row">
<div class="pi-title">
<h3>Testing</h3>
</div>
<div class="table-container col-md-12">
<table class="table" border='1' cellpadding='5' cellspacing='0' bordercolor='#ccc'>
<thead class="thead-dark">
<tr>
<th scope="col">ID</th>
<th scope="col">1</th>
<th scope="col">2</th>
<th scope="col">3</th>
</tr>
</thead>
<tbody>
<tr></tr>
<tr>
<?php
error_reporting(E_ALL amp; ~E_NOTICE);
array_multisort(array_map('filemtime', ($files = glob("*.*", GLOB_BRACE))), SORT_DESC, $files);
$dirs = array($dirname, $dirnameTwo, $dirnameThree);
foreach ($files as $filename) {
for ($i = 1; $i <= 12; $i ) {
if (file_exists($filename)) {
echo "</tr>";
echo "<td><font face='Arial' size='6'>$i</font></td>";
echo "<td><img src='$dirs[0]/$cam1[$i]' height='180' width='220'><br>" . date("F d Y H:i", filemtime($filename));
echo "</td>";
echo "<td><img src='$dirs[1]/$cam2[$i]' height='180' width='220'><br>" . date("F d Y H:i", filemtime($filename));
echo "</td>";
echo "<td><img src='$dirs[2]/$cam3[$i]' height='180' width='220'><br>" . date("F d Y H:i", filemtime($filename));
echo "</td>";
}
if ($i === 12) break;
}
if ($i === 12) break;
}
?>
</tr>
</tbody>
</table>
</div>
</div>
</div>
Ответ №1:
Здесь я сделаю это для 1 из них:
//covers a single folder
$dirname = "dir1";
$cam1 = [];
foreach(array_diff(scandir($dirname), ['.','..']) as $file){
$pathname = $dirname.DIRECORY_SEPERATOR.$file;
if(is_dir($pathname)) continue; //skip folders
$cam1[filemtime($pathname).'-'.$file] = $pathname;
}
ksort($cam1, SORT_NATURAL);
$latest = end($cam1);
В идеале вы должны использовать вышеуказанное в функции или цикле. Цикл или функция лучше, потому что, если вам нужно добавить другую папку, вы просто добавляете ее в массив или вызываете функцию с ней. Без этого (как у вас есть), если вы хотите добавить еще один, вам придется дублировать весь код для него. Для массива это было бы так:
//covers all 3 directories
$dirs = ["dir1","dir2","dir3"];
$results = [];
foreach($dirs as $dirname){
$res = [];
if(!is_dir($dirname)) continue; //or issue an error
foreach(array_diff(scandir($dirname), ['.','..']) as $file){
$pathname = $dirname.DIRECORY_SEPERATOR.$file;
if(is_dir($pathname)) continue; //skip folders
$res[filemtime($pathname).'-'.$file] = $pathname;
}
ksort($res, SORT_NATURAL);
$results[$dirname] = end($res);
}
//['dir1' => 'dir1/somefile.jpg', 'dir2' => ....]
Чтобы объяснить это.
array_diff
Удаляет пути типа .
или ..
, что является распространенной проблемой с scandir
. Это что-то вроде резервных папок.
Мы можем проверить, является ли указанный «путь» каталогом, чтобы пропустить файлы с continue в качестве дополнительной меры предосторожности.
Получаем время файла в виде метки времени UNIX, затем добавляем имя файла, потому что, если 2 файла были созданы в одну и ту же секунду, мы хотим сохранить их оба.
Затем мы можем отсортировать ключи, в которые следует (если я правильно помню) поместить самую высокую последнюю временную метку (или большую самую последнюю временную метку). Затем мы просто берем последний из массива с помощью end
.
scandir
Аргумент сортировки (аргумент 2) работает только с именами файлов.
Обновить
[как] я бы повторил временную метку
Ну, есть 2 простых способа, которые вы можете использовать filemtime
снова:
echo filemtime($results[$dirname]);
Или вы могли бы добавить это при циклическом просмотре:
foreach(array_diff(scandir($dirname), ['.','..']) as $file){
$pathname = $dirname.DIRECORY_SEPERATOR.$file;
if(is_dir($pathname)) continue; //skip folders
$filemtime = filemtime($pathname);
//$res[filemtime($pathname).'-'.$file] = $pathname;
//change the structure of this to:
$res[$filemtime.'-'.$file] = [
'pathname'=>$pathname,
'mtime' => $filemtime
];
}
И тогда вы бы сделали
echo $results[$dirname]['mtime'];
Для последнего я сделаю это как завершенную функцию (предпочтительно):
//all the above stuff wrapped in a function
function getLatestFromFolders($dirs, array $exclude = ['.','..']){
//normalize to array
if(!is_array($dirs)) $dirs = [$dirs];
$results = [];
foreach($dirs as $dirname){
//if(!is_dir($dirname)) continue; //or issue an error
if(!is_dir($dirname)) throw new Exception($dirname.' Not found');
$res = [];
foreach(array_diff(scandir($dirname), $exclude) as $file){
$pathname = $dirname.DIRECORY_SEPERATOR.$file;
if(is_dir($pathname)) continue; //skip folders
$filemtime = filemtime($pathname);
$res[$filemtime.'-'.$file] = [
'pathname'=>$pathname,
'mtime' => $filemtime
];
}//end foreach $files
ksort($res, SORT_NATURAL);
$results[$dirname] = end($res);
}//end foreach $dirs
return $results;
} //end getMyFolders
//call it like this for one path
$results = getLatestFromFolders('dir1');
echo $results['dir1']['mtime'];
echo $results['dir1']['pathname'];
//call it like this for multiple paths
$results = getLatestFromFolders(['dir1','dir2']);
echo $results['dir1']['mtime'];
echo $results['dir2']['mtime'];
//call it like this to exclude file .htaccess or any other files
//the ['.','..'] dosnt matter because of if(is_dir($pathname)) continue; //skip folders
$results = getLatestFromFolders(['dir1','dir2'], ['.htaccess']);
echo $results['dir1']['mtime'];
echo $results['dir2']['mtime'];
Непроверено, но теоретически должно работать. Я не могу протестировать его в sanbox из-за того, что scandir
в большинстве из них он отключен.
Так что простите за любые опечатки и т.д…
Я просто подумал об использовании preg_grep
или function getLatestFromFolders($dirs, $regex = '/. /'){ ... foreach(preg_grep($regex, scandir($dirname)) as $file)
для использования регулярного выражения против имен файлов. Затем вы могли бы сделать getLatestFromFolders($dir, '/.(jpg|png)$/')
etc и сопоставить расширения, но я оставлю это на другой день.
Спасибо!
Комментарии:
1. Для других каталогов мне нужно будет выполнить еще 2 цикла foreach? И в цикле, как бы я повторил временную метку?
2. @ArtisticPhooenix Спасибо за вашу помощь, пока что, приятель, она у меня самая близкая за всю неделю. Эхо метки времени (echo filemtime($results[$dirname]);) показывает ’01 января 1970 01:00′, и я предполагаю, что для второго столбца я просто использую тот же цикл, но меняю $ dirname на $ dirnameTwo?
3. Суть в том, чтобы ничего не менять в коде, но изменить входные данные, используемые кодом. Таким образом, код можно использовать повторно.
(echo filemtime($results[$dirname]);) is showing 'January 01 1970 01:00'
Что$results[$dirname]
это должно быть имя файла с путем.4. если вы используете последний пример функции,
One last one is this:
тогда вы должны сделать$results = getLatestFromFolders($dirname);
, а затемif(isset($results[$dirname])) echo $results[$dirname]['mtime'];
5. Я попробую сейчас, спасибо за вашу помощь, приятель, застрял на этом примерно на неделю, лол