Search code examples
phpdatetimearchive

How to create a archive list from an array of dates in php


I am looking to create a list in the following format:

2012 (2) 
- January (1) 
- March (1) 
2011 (1) 
- March (1)

from am array of dates in the following format:

Array
(
    [0] => Array
        (
            [year] => 2012
            [month] => 3
        )

    [1] => Array
        (
            [year] => 2012
            [month] => 1
        )

    [2] => Array
        (
            [year] => 2011
            [month] => 3
        )

)

this list is provided from the following query, and i'm open to suggestions as how to return the data as well. This was the most logical step for me.

SELECT YEAR(post_date) as `year`, MONTH(post_date) as `month` FROM posts ORDER BY post_date DESC

I'm at a dead end here. I don't know if I'm not seeing something obvious or if I've made this too complicated but I can't figure out where to go from here.


Solution

  • Assuming you might have multiple rows with the same month/year:

    # first sort into a 2-level array of post counts
    $by_year = array();
    $year_counts = array();
    foreach ($rows as $row){
        $by_year[$row['year']][$row['month']]++;
        $year_counts[$row['year']]++;
    }
    
    # most recent year first!
    krsort($by_year);
    
    # and now iterate for display
    foreach ($by_year as $year => $months){
    
        echo "<b>$year</b> ($year_counts[$year])<br />\n";
        echo "<ul>\n";
    
        # sort jan->dec
        ksort($months);
        foreach ($months as $month => $num){
    
            $name = date('F', mktime(0,0,0,$month,1,2010));
            echo "<li> $name ($num) </li>\n";
        }
    
        echo "</ul>\n";
    }
    

    This works as you requested, with this input data:

    $rows = array(
        array('year' => 2012, 'month' => 3),
        array('year' => 2012, 'month' => 3),
        array('year' => 2012, 'month' => 2),
        array('year' => 2011, 'month' => 1),
    );
    

    It outputs this:

    2012 (3)
     * February (1)
     * March (2)
    2011 (1)
     * January (1)
    

    *updated to show year counts too