tags:

views:

190

answers:

3

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  A: 

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
SeanJA
Cheers! Your idea is worked out great, thanks a bunch!
Tass
No prob, sorry that it is pseudocode, but I prefer to let people learn rather than give them the full answer right away
SeanJA
No, actually, that was the best way, as it let me adapt it to my code more easily. (I use "while loops" instead of "for loops", for example) Great stuff, great stuff.
Tass
A: 

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.

Tom Haigh
A: 
<?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.