I am using advanced custom fields pro to store and display information on estate sale dates. These are held in a repeater field, each row in the field has a start time, end time and a date. I need to display the information ordered by the date in the repeater field row. Currently it is ordered by date modified. I have tried several solutions but none seem to work for what I need to do.
This is what I have currently:
<?php
$latestes = new WP_Query(
array(
'post_type' => 'estate-sales',
'post_status' => 'publish',
'posts_per_page' => 10,
'orderby' => 'modified',
'order' => 'DESC'
)
);
while ( $latestes->have_posts() ) : $latestes->the_post();
echo '<li class="frontpage-esale"><a href="';
the_permalink();
echo '">';
the_title();
echo ' ';
$rowses = get_field('estate_sale_dates');
$first_row = $rowses[0];
$first_row_date = $first_row['es-date'];
$first_row_start = $first_row['es-start-time'];
$first_row_end = $first_row['es-end-time'];
echo ' - ';
if ($first_row_date) {
echo date('F j, Y',strtotime($first_row_date));
}
else {
echo 'Sale Dates TBA';
}
endwhile;
wp_reset_query();
?>
The most common answer when searching for a solution is to do something like this:
$latestes = new WP_Query(
array(
'post_type' => 'estate-sales',
'post_status' => 'publish',
'posts_per_page' => 10,
'orderby' => 'modified',
'order' => 'DESC'
)
);
while ( $latestes->have_posts() ) : $latestes->the_post();
$repeater = get_field('estate_sale_dates');
foreach( $repeater as $key => $row )
{
$column_id[ $key ] = $row['es-date'];
}
array_multisort( $column_id, SORT_ASC, $repeater );
foreach( $repeater as $row ) {
echo '<li class="frontpage-esale"><a href="';
the_permalink();
echo '">';
the_title();
echo ' ';
$rowses = get_field('estate_sale_dates');
$first_row = $rowses[0];
$first_row_date = $first_row['es-date'];
$first_row_start = $first_row['es-start-time'];
$first_row_end = $first_row['es-end-time'];
echo ' - ';
if ($first_row_date) {
echo date('F j, Y',strtotime($first_row_date));
}
else {
echo 'Sale Dates TBA';
}
}
endwhile;
wp_reset_query();
?>
However, when I try that, it lists each sale 3 times, does not order by the date at all, and if no date is entered (which needs to just default to Sale Dates TBA) it throws an error.
Any help greatly appreciated.
Note, that your integration isn't complete, signaled by having two get_field('estate_sale_dates');, and the name $first_row being out of place when iterating all of them. Without the sort, you're basically doing
$repeater = get_field( 'estate_sale_dates' );
...
foreach ( $repeater => $row_that_isnt_used )
{
$rowses = get_field( 'estate_sale_dates' );
$first_row = $rowses[0];
}
I think something like this is what you're after:
<?php
while ( $latestes->have_posts() ) {
$latestes->the_post();
echo '<li class="frontpage-esale"><a href="';
the_permalink();
echo '">';
the_title();
echo '</a> ';
if ( ! count( $sale_dates = get_field('estate_sale_dates') ) )
echo '<span>Sale Dates TBA</span>';
else
{
// $order = array_column( $sale_dates, 'es-date' ): (php 5.5+)
foreach( $sale_dates as $ignore => $row )
$order[] = $row['es-date'];
array_multisort( $order, SORT_ASC, $sale_dates );
echo "<ul>";
foreach( $sale_dates as $row ) {
$date = $row['es-date'];
$start = $row['es-start-time'];
$end = $row['es-end-time'];
echo "<li>" . date('F j, Y',strtotime($row_date)) . " $start-$end</li>";
}
echo "</ul>";
}
echo "</li>";
}
I have the same problem with a calendar. There is no solution to do this in the right way with a repater field. The best way to do this, is to use an custom field in an hidden post type and a relation field.
Because any PHP solution is inperformant.
Make a Custom Post Type "Sales Dates" an in this a custom field "date" and a second "Post Relation".
Then select from Post Type "Sales Dates" all Posts order by meta key "dates" with the relation field you get the data from the not hidden post type.
Related
I have a CPT - 'newsletters' and Taxonomy 'newsletter-groups'
I'm trying to display each post under it's respective term heading with all that terms posts displayed under it showing the Month and Year they were posted (by Postdate).
I thought I had something working , but noticed during testing that if a post had the same 'Month' it would wipe out the year and month for other posts in the same term and also for the terms below it , I have some images to show what I mean and the code I'm using so far.
In the images shown I've appended the post date to the filename for clarity , it would normally be just the filename.
Not Working if post date month is the same
Working if post date month is different
How can I solve this ? do I need to get all the post dates with a separate query and save that ?
Any examples appreciated
/*
* Custom Template: Archive Newsletters
*/
// Remove stuff
remove_action( 'genesis_loop', 'genesis_do_loop' );
// Add our custom loop
add_action( 'genesis_loop', 'newsletter_archive_loop' );
function newsletter_archive_loop() {
//fetch the terms for the newsletter-groups taxonomy
$terms = get_terms( 'newsletter-groups', array (
'hide_empty' => 'true',
'exclude' => 67, //excluding parent term ID 'school-newsletters' - only want to show term children of 'school-newsletters'
));
// run a query for each term
foreach( $terms as $term ) {
// Define the query
$args = array(
'post_type' => 'newsletters',
'newsletter-groups' => $term->slug ,
'posts_per_page' => -1,
);
// run the query
$query = new WP_Query( $args );
if( $query->have_posts() ) {
echo '<div class="letters">';
// output the term name in a heading tag
echo'<h4 class="term-heading">' . $term->name . '</h4>';
while ( $query->have_posts() ) { $query->the_post();
// get current month
$current_month = get_the_date('F');
// get attachements from custom field
$attachment_id = get_field('newsletter_upload');
$url = wp_get_attachment_url( $attachment_id );
$title = get_the_title( $attachment_id );
// get the filesize
$filesize = filesize( get_attached_file( $attachment_id ) );
$filesize = size_format($filesize, 2);
if( $query->current_post === 0 ) {
echo '<h4 class="date">';
the_date( 'F Y' );
echo '</h4>';
} else {
$f = $query->current_post - 1;
$old_date = mysql2date( 'F', $query->posts[$f]->post_date );
if($current_month != $old_date) {
echo '<h4 class="date">';
the_date( 'F Y' );;
echo '</h4>';
}
} ?>
<li class="letters-file">
<?php the_title(); ?><span class="letters-file-sz"> (<?php echo $filesize; ?>)</span>
</li>
<?php } // endwhile have posts
echo '</div>'; // close letters div
// use reset postdata to restore orginal query
wp_reset_postdata();
} // end if query have posts
} // end for each
} // end function
genesis(); // call genesis framework
Remove if and else both conditions and try to print only echo ''; the_date( 'F Y' ); echo ''
it will only show the individual post dates - But not grouped
EXPECTED OUTPUT
You can push each month in an array and check if the month is already in the array then do not display repeat month.
/*
* Custom Template: Archive Newsletters
*/
// Remove stuff
remove_action( 'genesis_loop', 'genesis_do_loop' );
// Add our custom loop
add_action( 'genesis_loop', 'newsletter_archive_loop' );
function newsletter_archive_loop() {
//fetch the terms for the newsletter-groups taxonomy
$terms = get_terms( 'newsletter-groups', array (
'hide_empty' => 'true',
'exclude' => 67, //excluding parent term ID 'school-newsletters' - only want to show term children of 'school-newsletters'
));
// run a query for each term
foreach( $terms as $term ) {
$dates = array();
// Define the query
$args = array(
'post_type' => 'newsletters',
'newsletter-groups' => $term->slug ,
'posts_per_page' => -1,
);
// run the query
$query = new WP_Query( $args );
if( $query->have_posts() ) {
echo '<div class="letters">';
// output the term name in a heading tag
echo'<h4 class="term-heading">' . $term->name . '</h4>';
while ( $query->have_posts() ) { $query->the_post();
// get current month
$current_month = get_the_date('F');
// get attachements from custom field
$attachment_id = get_field('newsletter_upload');
$url = wp_get_attachment_url( $attachment_id );
$title = get_the_title( $attachment_id );
// get the filesize
$filesize = filesize( get_attached_file( $attachment_id ) );
$filesize = size_format($filesize, 2);
if( !in_array(get_the_date( 'F Y' ), $dates ) ){
$dates[] = get_the_date( 'F Y' );
echo '<h4 class="date">';
echo get_the_date( 'F Y' );
echo '</h4>';
}
?>
<li class="letters-file">
<?php the_title(); ?><span class="letters-file-sz"> (<?php echo $filesize; ?>)</span>
</li>
<?php } // endwhile have posts
echo '</div>'; // close letters div
// use reset postdata to restore orginal query
wp_reset_postdata();
} // end if query have posts
} // end for each
} // end function
genesis(); // call genesis framework
I have tried to find a solution to something I need on the website (example here: https://www.baiweb.nl/). I have been looking for a way to show a custom number of posts per category AND sort them by date. I have managed to get a single post per category, but I can't seem to fix the rest. It sorts the posts itself by date now, but not all of them.
So, my questions are:
Is it possible to sort this loop, with all different categories, by date?
Is it possible to control the number of posts shown per category? This one is extra for me, not essential, but it would be nice.
Hope someone can help! Thanks a lot in advance for your time!
Here is my code used in the loop now:
<?php
$categories = get_categories();
$cats = array();
foreach($categories as $category) {
$cats[] = $category->name . ", ";
}
$exclude_posts = array();
foreach( $cats as $cat ) {
// build query argument
$query_args = array(
'category_name' => $cat,
'showposts' => 1,
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC'
);
// exclude post that already have been fetched
// this would be useful if multiple category is assigned for same post
if( !empty($exclude_posts) )
$query_args['post__not_in'] = $exclude_posts;
// do query
$query = new WP_Query( $query_args );
// check if query have any post
if ( $query->have_posts() ) {
// start loop
while ( $query->have_posts() ) {
// set post global
$query->the_post();
// add current post id to exclusion array
$exclude_posts[] = get_the_ID();
?>
<article id="post-<?php the_ID(); ?>" <?php post_class('loop');?>>
<div class="corner"><span><?php foreach((get_the_category()) as $category){ echo $category->name.'<br> '; } ?></span></div>
<!-- thumbnail -->
<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>" class="image">
<?php
$thumb_id = get_post_thumbnail_id();
$thumb_url = wp_get_attachment_image_src($thumb_id,'medium', true);
if ( in_category('2') || in_category('32') ) {
echo '<div class="newstitle">' . the_title() . '</div>';
}
else {
if ( has_post_thumbnail()) {
echo "<div class='ctr-image test2' style='background-image: url(" . $thumb_url[0] . ")'></div>";
}
else {
echo '<div class="newstitle">' . the_title() . '</div>';
}
}
?>
</a>
<div class="content">
<span class="date"><?php the_time('j/m/Y'); ?></span>
<h3>
<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">
<?php if ( in_category('2') || in_category('32') ) {}
else { echo the_title();} ?>
</a>
</h3>
<div class="text">
<?php html5wp_excerpt('html5wp_index'); // Build your custom callback length in functions.php ?>
</div>
</div>
</article>
<?php
// do something
}
} else {
// no posts found
}
// Restore original Post Data
wp_reset_postdata();
} ?>
You were close. Your categories foreach loop has to englobe everything. Then we do a simple loop but we specify what arguments to use depending on each categories.
Here is our final result.
<?php
$categories = get_categories(); // ... get all our categories
foreach( $categories as $category ) { // ... start foreach categories
if ( $category->name == 'Mercury' ) { // ... if our category name is 'Mercury'
$posts_per_page = 1; // ... 1 post per page if our category is named 'Mercury'
} else { // ... else, for all other categories
$posts_per_page = 3; // ... 3 posts per page
};
$args = array( // ... all our arguments
'posts_per_page' => $posts_per_page, // ... 1 or 3 posts per page depending on our categories
'post_type' => 'post',
'category_name' => $category->name,
'post_status' => 'publish',
'orderby' => 'date', // ... order by date
'order' => 'ASC', // ... most recent first
);
$query = new WP_Query( $args ); // .. start a new loop
if( $query->have_posts() ):
echo '<section>';
echo '<h1>' . $category->name . '</h1>'; // ... only display our section IF a post exist in the category
while( $query->have_posts() ): $query->the_post();
echo '<article>'; // ... our post template
the_title( '<h4>', '</h4>' );
echo '</article>';
endwhile;
echo '</section>';
endif;
wp_reset_postdata(); // ... After looping through a separate query, this function restores the $post global to the current post in the main query.
}; // ... end foreach categories
?>
Thank you so much for your quick and comprehensive answer! The part of the number of categories is working very well, however, the outcome is slightly different than I want. It may be that my question was not clear, apologies for that.
What you have already made beautiful is all the categories with posts that belong to it. What I want to achieve is that all messages are mixed up, sorted by date and, what was already done here, I can indicate how many posts are in per category. Is that even possible?
Some screenshotsof the outcome of your code:
This is what I am trying, except now I need to sort this by date:
This is the code slightly adjusted:
<?php
$categories = get_categories(); // ... get all our categories
foreach( $categories as $category ) { // ... start foreach categories
if ( $category->name == 'Mercury' ) { // ... if our category name is 'Mercury'
$posts_per_page = 1; // ... 1 post per page if our category is named 'Mercury'
} else { // ... else, for all other categories
$posts_per_page = 2; // ... 3 posts per page
};
$args = array( // ... all our arguments
'posts_per_page' => $posts_per_page, // ... 1 or 3 posts per page depending on our categories
'post_type' => 'post',
'category_name' => $category->name,
'post_status' => 'publish',
'orderby' => 'date', // ... order by date
'order' => 'ASC', // ... most recent first
);
$query = new WP_Query( $args ); // .. start a new loop
if( $query->have_posts() ):
// echo '<section>';
// echo '<h1>' . $category->name . '</h1>'; // ... only display our section IF a post exist in the category
while( $query->have_posts() ): $query->the_post();
echo '<article>'; // ... our post template
echo '<h1>' . $category->name . '</h1>';
the_time('j/m/Y');
the_title( '<h4>', '</h4>' );
echo '</article>';
endwhile;
// echo '</section>';
endif;
wp_reset_postdata(); // ... After looping through a separate query, this function restores the $post global to the current post in the main query.
}; // ... end foreach categories ?>
Hope this is clear, thanks again!
I have two fairly complex WordPress queries that I need to combine into a single query.
In my first query, I am getting Wordpress Posts by the date they are published. Each day of posts is contained inside a container, with the date showed above the posts as a title. It also only hides any posts that are in the past. Only posts from today or the future are shown.
In my second query, I am getting WordPress Posts from a Custom Taxonomy. For each term in the taxonomy, posts are displayed inside a container utilizing the slug of that term as a class, and displaying the name of the term as the title.
What I need to accomplish and what I need help with, is as follows.
I need the first query exactly as it is now, however, in the first query, where it says "// Need code here to display posts by taxonomy term //", I need to integrate the second query so that where posts are being output for that day, its also listing the posts by the term like in the second query.
Both queries function perfectly on their own, but I am having trouble with implementing a single query that utilizes the functionality from both queries to do what I need to do.
Here are my two queries:
1st Query:
<?php
// First we get yesterdays date
$year = date("Y"); $month = date("m"); $yesterday = date("d", strtotime("-1 day"));
// Then we construct a query to get items from the calendar, either published or scheduled for a future date so that they appear on the calendar. We use date query to hide events that have already passed by querying after the date we got before. We use yesterdays date to ensure that TODAYS post are still obtained
$query = new WP_Query(array('post_type' => 'calendar',
'post_status' => 'publish,future',
'orderby' => 'post_date',
'order' => 'DESC',
'date_query' => array(
array('after' => array(
'year' => $year,
'month' => $month,
'day' => $yesterday
)
)
)
));
// This is a special loop that gets posts by day and encases each days worth of posts in a container and shows the date of those posts. jQuery will be applied to this
if ($query->have_posts()) {
echo '<div class="day-posts">';
while ($query->have_posts()) {
$query->the_post();
echo '<div class="day">';
the_date('l jS F Y', '<div class="title"><div>', '</div>'); //Formats date, before echo, after echo
echo '<div class="posts clearfix">';
echo '<div class="post">';
the_title('<div class="title">', '</div>');
echo '<div class="content">';
// Need custom code here to display posts by taxonomy //
the_content();
echo '</div></div></div></div>';
}
echo '</div>';
}?>
2nd Query:
<?php
$post_type = array('calendar');
$tax = 'event-category';
$tax_terms = get_terms($tax, array('orderby' => 'id', 'order' => 'ASC'));
if ($tax_terms) {
foreach ($tax_terms as $tax_term) {
$args = array(
'post_type' => $post_type,
"$tax" => $tax_term->slug,
'post_status' => 'publish',
'posts_per_page' => - 1,
'caller_get_posts' => 1
); // END $args
$my_query = null;
$my_query = new WP_Query($args);
if ($my_query->have_posts()) {
echo '<div class="' . $tax_term->slug . '">';
echo '<div class="title">' . $tax_term->name . '</div>;
while ($my_query->have_posts()) : $my_query->the_post();
?>
<?php the_title();?>
<?php the_content();?>
<?php endwhile; echo '</div>'; } wp_reset_query(); } } ?>
I hope I have done a good job of explaining what I am trying to do. If I have not, or there are questions, please ask and I'll answer as quick as I can.
Ok here you go (I dont have posts setup like your query so i didn't test it but i believe this what you are looking for):
// Setup the basic structure:
$args = array(
'post_type' => 'calendar',
'post_status' => 'publish,future',
'orderby' => 'post_date',
'order' => 'DESC',
'date_query' => array(
array(
'after' => array(
'year' => $year,
'month' => $month,
'day' => $yesterday
)
)
),
'posts_per_page' => -1,
'caller_get_posts' => 1
);
// For dynamic taxonomy term create a bootstrap tax_query
$tax = 'event-category';
$tax_terms = get_terms($tax, array('orderby' => 'id', 'order' => 'ASC'));
if ($tax_terms) {
$args['tax_query'] = array(
array(
'taxonomy' => $tax,
'field' => 'slug',
)
);
// Append the slugs to the tax_query terms
foreach ($tax_terms as $tax_term) {
$args['tax_query'][0]['terms'][] = $tax_term->slug;
}
}
// Your One and only QUERY
$my_query = new WP_Query($args);
For $tax_term->slug and $tax_term->name you could use get_the_terms() within the query loop like:
$terms = get_the_terms($post->ID, $tax);
$terms = array_slice($terms, 0);
$term = $terms[0];
echo $term->slug;
echo $term->name;
EDITED
See code comments for explanation/clarification
if ($query->have_posts()) {
$_tax = false;
$same_date = array(); // collection of same dates
$same_date_bool = true; // determine previous post date exist
echo '<div class="day-posts">';
while ($query->have_posts()) {
$query->the_post();
$date = get_the_date('l jS F Y');
$same_date_bool = true;
// Checking if post is displayed from the current date
// then this post should be appended inside to previous
// opened div.day tag
if (!empty($same_date) && in_array($date, $same_date)) {
$same_date_bool = false;
}
// Collecting all dates
$same_date[] = $date;
// If post is not in same date
// create new div element
if ($same_date_bool) {
echo '<div class="day">
<div class="title">';
echo $date;
echo '</div>';
}
// If post is not in same date
// create new div element
if ($same_date_bool) {
echo '<div class="posts clearfix">';
}
echo '<div class="post">';
the_title('<div class="title">', '</div>');
echo '<div class="content">';
$terms = get_the_terms($post->ID, $tax);
// Note: I'm assuming your post will
// always have single term
$terms = array_slice($terms, 0);
$term = $terms[0];
if ($term) {
$_tax = true;
echo '<div class="' . $term->slug . '">';
echo '<div class="title">' . $term->name . '</div>';
}
the_content();
if ($_tax) {
echo '</div>';
}
echo '</div></div>';
// If post is in same date
// append closing div element for previous "div.day" element
if (!$same_date_bool) {
echo '</div></div>';
}
}
echo '</div>';
}
Hope this helps now. Also I have replaced the caller_get_posts with ignore_sticky_posts because caller_get_posts has been deprecated since v3.1
I have a Custom post type of "events" and I have a custom metabox for the date of the event. All events added with all dates recorded into database in srtotime() UNIX format.
When list of events is queried I need to separate them by week. So.. "week of 4/23" then list the events for that week only.. followed by "Week of 4/30" with the events for that week listed.
All of this needs to be dynamic and logically detect when each week begins and compare that to the date that is saved in the database for the returned events, thus grouping them into "weeks."
I hope that all makes sense. I am just having trouble finding resources for this type of functionality, and I am uncertain of the logic needed and what WP might already have I could use.
As of now the results are being pulled using a custom Wordpress loop, but I could use SQL if needed.
Thanks in advance for helping any way you can!
*UPDATED CODE
<?php
$loop = new WP_Query(array(
'post_type' => 'tf_events',
'posts_per_page' => -1,
'orderby' => 'meta_value',
'meta_key' => 'tf_events_startdate',
'order' => 'ASC'
));
echo '<pre>';
print_r($loop);
echo '</pre>';
$groups = array();
if ($loop->have_posts()) {
while ($loop->have_posts()) {
$loop->the_post();
$groups['Week of ' . $post->post_date][] = $post;
// Get event dates from WP metabox data (returns as string)
$longstartdate = get_post_meta($post->ID, 'tf_events_startdate', true); //get start date meta data
$longenddate = get_post_meta($post->ID, 'tf_events_enddate', true); //get start date meta data
$longweekof = get_post_meta($post->ID, 'tf_events_weekof', true); //get Week Of date meta data
// Reformat dates
$prettystartdate = date("D. M. j, Y", $longstartdate);
$prettyenddate = date("l, F j, Y", $longenddate);
$prettyweekof = date("m/d", $longweekof);
// Get Custom Meta Terms/Catagories/taxonomies
$the_venue = get_the_term_list( $post->ID, 'venue' );
$event_age = get_the_term_list( $post->ID, 'event_age' );
// Get Custom Metabox Data - URL for Buy Tickets
$buytix = get_post_meta( $post->ID, 'buytix', true );
}
}
?>
<h1>Groups of posts</h1>
<?php echo '<pre>'; print_r($groups); echo '</pre>';?>
<?php foreach ($groups as $week => $rows) : ?>
<h2><?php echo $week ?></h2>
<ul>
<?php foreach ($rows as $post) : setup_postdata($post) ?>
<?php echo ' <h1>POST START</h1> <pre>';
print_r($post);
echo '</pre> <h1>POST END</h1>'; ?>
<li><?php the_title() ?> <?php echo $prettystartdate; ?></li>
<?php endforeach ?>
</ul>
<?php endforeach ?>
When I need to group elements I normally use an associative array where the key is the thing to group by. So in your case the array would look something like:
array(
'Week of 4/30' => array(array of posts)
);
An easy way to do this (once you have all the posts) is like this:
$groups = array();
foreach ($posts as $post) {
$groups['Week of ' . date('m/d', $post->pub_date)][] = $post;
}
And then you can just:
foreach ($groups as $title => $posts) {
echo "<h2>$title</h2>";
foreach ($posts as $post) ...
}
Edit: Here's what a more complete code (including WP query etc) would look:
<?php
# Get all posts
$loop = new WP_Query(array(
'post_type' => 'tf_events',
'posts_per_page' => -1,
'orderby' => 'meta_value',
'meta_key' => 'tf_events_startdate',
'order' => 'ASC'
));
$groups = array();
# Create groups of posts
if ($loop->have_posts) {
while ($loop->have_posts()) {
$loop->the_post();
$groups['Week of ' . date('m/d', $post->tf_events_weekof)][] = $post;
}
}
?>
<h1>Groups of posts</h1>
<?php foreach ($groups as $week => $rows) : ?>
<h2><?php echo $week ?></h2>
<ul>
<?php foreach ($rows as $post) : setup_postdata($post) ?>
<li><?php the_title() ?></li>
<?php endforeach ?>
</ul>
<?php endforeach ?>
Here is rough solution that is working for me.
<?php
$loop = new WP_Query(array(
'post_type' => 'tf_events',
'posts_per_page' => -1,
'orderby' => 'meta_value',
'meta_key' => 'tf_events_startdate',
'order' => 'ASC'
));
$groups = array();
$heading = '';
if ($loop->have_posts()) {
while ($loop->have_posts()) {
$loop->the_post();
//set up pretty week
$weekof = get_post_meta($post->ID, 'tf_events_weekof', true); //get Week Of date meta data
$longstartdate = get_post_meta($post->ID, 'tf_events_startdate', true); //get start date meta data
$longenddate = get_post_meta($post->ID, 'tf_events_enddate', true); //get start date meta data
//format dates
$prettyweekof = date("m/d", $weekof);
$prettystartdate = date("D. M. j, Y", $longstartdate);
$prettyenddate = date("l, F j, Y", $longenddate);
//set info on objects
$post->prettyweekof = $prettyweekof;
$post->pretty_startdate = $prettystartdate;
$post->pretty_enddate = $prettyenddate;
//Echo heading when need to
if($post->prettyweekof !== $heading)
{
$heading = $post->prettyweekof;
echo '<h2>'.$heading.'</h2>';
}
//list events
echo $post->post_title.' | '.$post->pretty_startdate.' - '.$post->pretty_enddate.'<br />';
}
}
?>
I want to create an archive page template for Wordpress that will look like this:
August 2009
Post 4
Post 3
Post 2
Post 1
July 2009
Post 2
Post 1
So, basically, I want all the posts from the blog, ordered descending by date and grouped by month.
Can someone provide me the PHP code for this?
Thanks!
PS: Wordpress version is 2.8.2
This is a function I created a while back. It basically does what you want to do, but it's not a template. Maybe you can adapt it.
<?php
/**
* Displays a condensed list of the posts grouped by month/year.
*
* #param $order The order of the posts. Either 'DESC' or 'ASC', case sensitive.
* #param $date_prefix Whether to prefix the posts with the month/date.
* #param $display Whether to display the results or return it as a String.
*/
function condensed_post_list($order='DESC', $date_prefix=true, $display=true){
global $wpdb;
if( !in_array($order, array('DESC','ASC' ) ) ) $order = 'DESC';
$query = "SELECT ID, post_title, post_date FROM $wpdb->posts ".
"WHERE post_type='post' AND post_status = 'publish' ".
"ORDER BY post_date $order";
$results = $wpdb->get_results( $query );
ob_start();
$current_month = '';
foreach( $results as $result ) {
if( $current_month != mysql2date('F Y', $result->post_date)) {
if( $current_month ) echo '</ul>';
$current_month = mysql2date('F Y', $result->post_date );
echo '<h2>'.$current_month.'</h2>';
echo '<ul>';
}
echo '<li>';
echo ($date_prefix ? mysql2date('M j: ', $result->post_date) : '');
echo '<a href="'.get_permalink($result->ID).'">';
echo $result->post_title.'</a></li>';
}
if( $current_month ) echo '</ul>';
if( $display ) {
ob_end_flush();
} else {
return ob_get_clean();
}
}
?>
I used the above function, but replaced the SQL query with:
$results = query_posts('post_type=post&post_status=publish&cat=3');
This allowed me to use the excellent function #scompt.com wrote, but limit it to a single blog category.
Thanks a lot of the help. This is what I used with the code above.
function condensed_post_list($order='DESC', $date_prefix=true, $display=true)
{
if( !in_array($order, array('DESC','ASC' ) ) ) $order = 'DESC';
$args = array(
'numberposts' => -1,
'orderby' => 'post_date',
'post_type' => 'post',
'post_status' => 'publish');
$results = get_posts($args);
ob_start();
$current_month = '';
foreach( $results as $result ) {
if( $current_month != mysql2date('F Y', $result->post_date)) {
if( $current_month ) echo '</ul>';
$current_month = mysql2date('F Y', $result->post_date );
echo '<h2>'.$current_month.'</h2>';
echo '<ul>';
}
echo '<li>';
echo ($date_prefix ? mysql2date('M j: ', $result->post_date) : '');
echo '<a href="'.get_permalink($result->ID).'">';
echo $result->post_title.'</a></li>';
}
if( $current_month ) echo '</ul>';
if( $display ) {
ob_end_flush();
}
else {
return ob_get_clean();
}
}