问题
So! Basically I have a database with a load of blog posts, these are all sorted by a UNIX timestamp, and what I need is a way to make this code spit out headers when appropriate, so that it will output something like this:
2008
November
Title 1 - Date Goes Here
Title 2 - Date Goes Here
December
Title 3 - Date Goes Here
2009
January
Title 4 - Date Goes Here
etcetera
Here's my code so far, it works until the comparison of the year, and I still need to come up with a good way of how to make it compare months in a sensible fashion, so that January indeed comes after December, and not some ludicrous 13th month.
[code]
<?php
if ($db = new PDO('sqlite:./db/blog.sqlite3')) {
$stmt = $db->prepare("SELECT * FROM news ORDER BY date DESC");
if ($stmt->execute()) {
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
$current_year = date("Y", $row[1]);
$current_month = date("m", $row[1]);
if ($current_year > $last_year) {
echo "<h1>" . $current_year . "</h1>";
$last_year = $current_year;
}
echo "<tr>";
echo "<td align='left'><a href='view_post.php?post_id=". $row[1] ."'>" . $row['0'] . " - " . date("Y-m-d, H:i:s", $row[1]) . "</a></td>";
echo "</tr>";
}
}
} else {
die($sqliteerror);
}
?>
[/code]
回答1:
With unix timestamps you could do something like (pseudo code obviously)
prev_month = null
prev_year = null
foreach results as r
new_month = date('F', r[timestamp]);
new_year = date('Y', r[timestamp]);
if(prev_month != new_month)
//display month
/if
if(prev_year != new_year)
//display year
/if
// display other info
prev_month = new_month
prev_year = new_year
/foreach
回答2:
<?php
if ($db = new PDO('sqlite:./db/blog.sqlite3')) {
$stmt = $db->prepare("SELECT * FROM news ORDER BY date DESC");
if ($stmt->execute()) {
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
$current_year = date("Y", $row[1]);
$current_month = date("n", $row[1]); # n instead of m
if ($current_year > $last_year) {
echo "<h1>" . $current_year . "</h1>";
echo "<h2>" . $current_month . "</h2>";
$last_year = $current_year;
$last_month = $current_month;
}
elseif ($current_month > $last_month) {
echo "<h2>" . $current_month . "</h2>";
$last_month = $current_month;
}
echo "<tr>";
echo "<td align='left'><a href='view_post.php?post_id=". $row[1] ."'>" . $row['0'] . " - " . date("Y-m-d, H:i:s", $row[1]) . "</a></td>";
echo "</tr>";
}
}
} else {
die($sqliteerror);
}
?>
I did not test it. Idea: If the year changes, also the month changes. The check for the next month happens only if there is not a change of the year, which is the only case where lastmonth might be bigger than currentmonth.
回答3:
I would be tempted to do this in two steps, separating the database fetching from the display/html logic, for example:
<?php
//snip
//make big array of archive
$archive = array();
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
$year = date("Y", $row[1]);
$month = date("m", $row[1]);
if (!isset($archive[$year])) {
$archive[$year] = array();
}
if (!isset($archive[$year][$month])) {
$archive[$year][$month] = array();
}
$archive[$year][$month][] = $row;
}
//snip
//loop over array and display items
?>
<?php foreach ($achive as $year => $months): ?>
<h1><?php echo $year; ?></h1>
<?php foreach ($months as $month => $posts): ?>
<h2><?php echo $month; ?></h2>
<ul>
<?php foreach ($posts as $post): ?>
<li><?php echo $post[0]; ?> etc...</li>
<?php endforeach; ?>
</ul>
<?php endforeach; ?>
<?php endforeach; ?>
You should get the years and the months in reverse order as per your SQL query. I haven't tested this, but it should be vaguely correct.
来源:https://stackoverflow.com/questions/1060622/php-blog-need-to-make-a-good-looking-archives-section