Reputation: 536
Yes, I know this is ugly code :) And it doesn't work.
I'm globbing all the .php files in a directory and then sorting them by file timestamp, and then I want to echo the file names into each month. But how do I fix this loop so the echoed output of each month is correct? The files by $path are sorted by date, but the $link_title is the same for all files in all months, so I don't see that the $paths are getting arranged by month.
foreach (glob("*.php") as $path) {
$files[$path] = filemtime($path);
} arsort($files);
$currentdate = strtotime(date("Y-m-d H:i:s"));
$julybegin = strtotime("2018-07-01 00:00:00");
$julyend = strtotime("2018-07-31 23:23:59");
$junebegin = strtotime("2018-06-01 00:00:00");
$juneend = strtotime("2018-06-30 23:23:59");
$maybegin = strtotime("2018-05-01 00:00:00");
$mayend = strtotime("2018-05-31 23:23:59");
$aprilbegin = strtotime("2018-04-01 00:00:00");
$aprilend = strtotime("2018-04-30 23:23:59");
$timestamp = filemtime ($path);
$link_title = $path;
foreach ($files as $path => $timestamp) {
if($timestamp > $julybegin && $timestamp < $julyend) {
echo '<li>';
echo $path . ' ' . $link_title;
echo '</li>';
} else {
if($timestamp > $junebegin && $timestamp < $juneend) {
echo '<li>';
echo $path . ' ' . $link_title;
echo '</li>';
} else {
if (($timestamp >= $maybegin) && ($timestamp <= $mayend)){
echo '<li>';
echo $path . ' ' . $link_title;
echo '</li>';
} else {
if (($timestamp >= $aprilbegin) && ($timestamp <= $aprilend)){
echo '<li>';
echo $path . ' ' . $link_title;
echo '</li>';
}
}
}
}
}
Edit 6/21/18
This works and outputs the correct markup for a jQuery accordian:
foreach (glob("*.php") as $path) {
$timestamp = filemtime($path);
$files[date('F', $timestamp)][$path] = $timestamp;
}
arsort($files);
echo '<div class="accordion">';
foreach ($files as $month => $paths) {
krsort($paths);
echo '<h6>' . $month . '</h6><div><ul>';
foreach ($paths as $path => $timestamp) {
echo '<li>' . $path . '</li>';
}
echo '</ul></div>';
}
echo '</div>';
Upvotes: 0
Views: 676
Reputation: 11328
Since your end-goal is to group the filenames by month, you need a loop to show you only the entries from the $files
array that match a particular month:
$months = array(
'2018-07',
'2018-06',
'2018-05',
'2018-04'
);
foreach ($months as $month) {
// just some example markup
echo '<p>' . $month . '</p>';
echo '<ul>';
foreach ($files as $path => $timestamp) {
if (date('Y-m', $timestamp) == $month) {
echo '<li>' . $path . '</li>';
}
}
echo '</ul>';
}
If you already know that you're not going to use your $files
array for anything else, another option might be to simply group the files while processing the glob
results:
foreach (glob("*.php") as $path) {
$timestamp = filemtime($path);
$files[date('Y-m', $timestamp)][$path] = $timestamp;
}
Since it's now a nested array, you can't simply arsort()
the whole thing. But you can delay that until you want to loop over the file list to generate the desired HTML output:
// first sort the whole thing by keys (year + month), so that the months are sorted:
krsort($files);
foreach ($files as $month => $paths) {
// now sort the paths by their timestamps
arsort($paths);
// and output whatever markup you want
echo '<p>' . $month . '</p>';
echo '<ul>';
foreach ($paths as $path => $timestamp) {
echo '<li>' . $path . '</li>';
}
echo '</ul>';
}
EDIT AFTER THE UPDATED QUESTION
You seem to be misunderstanding a basic concept of defining variables in loops.
You have two separate loops in your code: one that processes the result of glob()
and one that turns the result of that processing into markup for your jQuery accordion.
By defining $monthname
in the first loop, it will maintain its last value when processing the glob()
result is finished.
You want to use $monthname
in the second loop, but you're not setting it there. Therefore, it will always be the same value: the last value it was when processing the glob()
result. Instead, you should define $monthname
where you want to use it.
Sidenote: I used
date('Y-m')
in my answer as an example, since I didn't know what you were going to display. If you always want to display the date asdate('F')
, you can simply use that for the array key instead. Then there's no need to keep track of a separate$monthname
variable and you can simply output the$month
value in the second loop. However, this might not be what you want, if you have files in there that have been modified in the same month but in different years.
As for the specific warnings you're seeing, they are caused by the fact that you're storing each file into the $files
array twice now:
foreach (glob("*.php") as $path) {
if($path == 'index.php') {
continue;
} // removes all files names index.php
/**** HERE: ****/
$files[$path] = filemtime($path);
$timestamp = filemtime ($path);
// needed to define $timestamp
/**** AND HERE: ****/
$files[date('Y-m', $timestamp)][$path] = $timestamp;
$monthname = (date('F', $timestamp));
// display month full name instead of month numeral
}
This means that the $files
array looks something like this:
Array
(
[/var/www/file.php] => 1529239095
[2018-06] => Array
(
[/var/www/file.php] => 1529239095
)
)
Because you still have that first assignment in there, you now occasionally try to sort (which you copy/pasted incorrectly, it should be an arsort()
instead of krsort()
) a timestamp (integer) instead of an array of path => timestamp
entries. You should remove that first assignment.
Upvotes: 2