$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>theme development - Custom post type archive sorted and grouped by date in post meta field|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

theme development - Custom post type archive sorted and grouped by date in post meta field

matteradmin9PV0评论

I am trying to build an Custom Post Type for showing information about events. The Custom Post Type has name 'Event', with the following meta fields:

  • event_startdate (date in format YYYY-MM-DD)
  • event_enddate (date in format YYYY-MM-DD)

This works fine for the single-event listing, however in the archive listing I would like to see a grouping like:

2019

March

  • Title of event starting in march
  • Title of another event starting in march

May

  • Title of may event

December

  • Title of Christmas event

2020

January

  • Title of 2020 vision event

I have found some questions and answers on using wp_get_archives(), however this seems to group the posts by published date, rather on the actual date of the event (event.startdate). I also found some posts on sorting by metavalue, however not grouping. Thanks in advance for any advice or hint on how to accomplish this!

I am trying to build an Custom Post Type for showing information about events. The Custom Post Type has name 'Event', with the following meta fields:

  • event_startdate (date in format YYYY-MM-DD)
  • event_enddate (date in format YYYY-MM-DD)

This works fine for the single-event listing, however in the archive listing I would like to see a grouping like:

2019

March

  • Title of event starting in march
  • Title of another event starting in march

May

  • Title of may event

December

  • Title of Christmas event

2020

January

  • Title of 2020 vision event

I have found some questions and answers on using wp_get_archives(), however this seems to group the posts by published date, rather on the actual date of the event (event.startdate). I also found some posts on sorting by metavalue, however not grouping. Thanks in advance for any advice or hint on how to accomplish this!

Share Improve this question edited Feb 17, 2019 at 19:16 Krzysiek Dróżdż 25.6k9 gold badges53 silver badges74 bronze badges asked Feb 17, 2019 at 16:45 Ole Kristian LosvikOle Kristian Losvik 1572 silver badges9 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 2

OK, so this problem has two parts:

  1. Make WordPress to sort these posts properly.
  2. Make WordPress to display them with all that grouping.

1. Sorting CPT by meta value on archive

You can use pre_get_posts to achieve this.

add_action( 'pre_get_posts', function ( $query ) {
    if ( is_post_type_archive( 'event' ) && $query->is_main_query() ) {
        $query->set( 'orderby', 'meta_value' );
        $query->set( 'order', 'ASC' );
        $query->set( 'meta_key', 'event_startdate' );
    }
} );

So now events will be sorted ascending by start_date.

2. Displaying and grouping

You'll have to modify the archive-event.php file, so these events get in their groups.

<?php
    $current_year = $current_month = '';

    while ( have_posts() ) :
        the_post();

        $last_year = $current_year;
        $last_month = $current_month;

        $current_year = date( 'Y', strtotime( get_post_meta( get_the_ID(), 'event_startdate', true ) ) );
        if ( $last_year != $current_year ) {
            $last_month = '';
        }
        $current_month = date( 'F', strtotime( get_post_meta( get_the_ID(), 'event_startdate', true ) ) );
?>
    <?php if ( $last_year != $current_year ) : ?><h2><?php echo $current_year; ?></h2><?php endif; ?>
    <?php if ( $last_month != $current_month ) : ?><h3><?php echo $current_month; ?></h3><?php endif; ?>
    <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
<?php endwhile; ?>

Based on the code from @krzysiek-dróżdż my archive-eventi.php is now like below. Posting it here incase anyone else is trying to achieve the same thing. Note that the event custom post type is named eventi.

<?php
/**
 * The template for displaying event archive
 *
 * @package Eventi
 * @since 1.0.0
 */
get_header();
?>

    <section id="primary" class="content-area">
        <main id="main" class="site-main">

        <?php
        if ( have_posts() ) :
            ?>

            <header class="page-header">
                <?php
                    the_archive_title( '<h1 class="page-title">', '</h1>' );
                ?>
            </header><!-- .page-header -->

            <?php
            // Start the Loop.
            $args = [
                'post_status'    => 'publish',
                'post_type'      => 'eventi',
                'posts_per_page' => 100,
                'orderby'        => 'meta_value',
                'order'          => 'ASC',
                'meta_type'      => 'DATE',
                'meta_key'       => 'eventi_startdate',
            ];

            $posts         = new WP_Query( $args );
            $current_year  = '';
            $current_month = '';
            while ( $posts->have_posts() ) {
            ?>
            <article id="event-<?php the_ID(); ?>" <?php post_class(); ?>>
                <div class="entry-content">
                <?php
                $posts->the_post();
                $post_id = get_the_id();

                $startdate  = strtotime( get_post_meta( $post_id, 'eventi_startdate', true ) );
                $enddate    = strtotime( get_post_meta( $post_id, 'eventi_enddate', true ) );
                $dateformat = get_option( 'date_format' );

                $last_year    = $current_year;
                $last_month   = $current_month;
                $current_year = date_i18n( 'Y', $startdate );
                if ( $last_year != $current_year ) {
                    $last_month = '';
                }
                $current_month = date_i18n( 'F', $startdate );

                if ( $last_year != $current_year ) {
                    echo '<h2>' . $current_year . '</h2>';
                }

                if ( $last_month != $current_month ) {
                    echo '<h3>' . $current_month . '</h3>';
                }

                $post_id = get_the_ID();
                if ( is_sticky() && is_home() && ! is_paged() ) {
                    printf( '<span class="sticky-post">%s</span>', _x( 'Featured', 'post', 'eventi' ) );
                }
                echo '<a href="' . esc_url( get_permalink() ) . '" class="event-details-link">' . get_the_title() . '</a>';
                echo '&nbsp;&nbsp;&mdash;&nbsp;&nbsp;' . get_the_excerpt();

                // Date and times


                echo '&nbsp;&nbsp;&mdash;&nbsp;&nbsp;' . date_i18n( $dateformat, $startdate );
                if ( $startdate !== $enddate ) {
                    echo ' - ' . date_i18n( $dateformat, $enddate );
                }

                ?>
                </div>
            </article>
            <?php
            }
            wp_reset_postdata();

            // If no content, include the "No posts found" template.
        else :
            ?>
            <section class="no-results not-found">
                <header class="page-header">
                    <h1 class="page-title"><?php _e( 'No events yet!', 'eventi' ); ?></h1>
                </header><!-- .page-header -->

                <div class="page-content">
                    <?php
                    if ( current_user_can( 'publish_posts' ) ) :

                        printf(
                            '<p>' . wp_kses(
                                /* translators: 1: link to WP admin new post page. */
                                __( 'Ready to publish your first event? <a href="%1$s">Get started here</a>.', 'eventi' ),
                                array(
                                    'a' => array(
                                        'href' => array(),
                                    ),
                                )
                            ) . '</p>',
                            esc_url( admin_url( 'post-new.php?post_type=eventi' ) )
                        );
                    else :
                        ?>

                        <p><?php _e( 'It seems we can&rsquo;t find any events.', 'eventi' ); ?></p>
                        <?php

                    endif;
                    ?>
                </div><!-- .page-content -->
            </section><!-- .no-results -->
            <?php
        endif;
        ?>
        </main><!-- #main -->
    </section><!-- #primary -->

<?php
get_footer();
Post a comment

comment list (0)

  1. No comments so far