【问题标题】:WordPress: Order WP_Query by custom date field and split the loop after every monthWordPress:按自定义日期字段排序 WP_Query 并在每个月之后拆分循环
【发布时间】:2018-03-11 16:16:26
【问题描述】:

我正在使用 WordPress 自定义帖子类型来管理和显示我网站上的事件。 为了对事件进行排序,我使用了一个包含日期的自定义元字段(存储方式如下:YYYY-MM-DD)。我根据当前日期检查元字段。像这样:

$current_date_query = date ('Y-m-d');

$temp = $wp_query; $wp_query= null; $wp_query = new WP_Query();

$wp_query->query(
    array(
       'post_type' => 'event',
       'meta_key' => 'event_date',
       'meta_compare' => '>=',
       'meta_value' => $current_date_query,
       'post_status' => 'publish',
       'posts_per_page' => '99',
       'orderby' => 'meta_value',
       'order' => 'ASC',
       'paged' => $paged
    )
); ?>


... Loop stuff ...

<?php endif; $wp_query = null; $wp_query = $temp; wp_reset_query(); ?>

我现在想在每个新月之前添加一个标题。像这样:

2018 年 1 月

  • 事件 1
  • 事件 2
  • 事件 3

2018 年 2 月

  • 事件 4
  • 事件 5

2018 年 3 月

  • 事件 5

等等……

有没有办法在每个月之后拆分循环? 我想我必须使用元字段中的月份,但我不知道如何。

我尝试了以下解决方案(感谢@FluffyKitten 的评论):

<?php

/* declare an array to save the data */
$quarters = array();

foreach($posts as $q) {

    $donor_date = get_post_meta($q->ID,'gid_22',true);
    $donor_month = date('m',strtotime($donor_date));

    /* format the date once - best practice is not to repeat code */
    $formatteddate = date('d/m/Y',strtotime($donor_date));

    /* organise the dates by quarter, using the heading as the key for easy display */
    if(in_array($donor_month, array('01')))
       $quarters["January"][] = $formatteddate;

    else if(in_array($donor_month, array('02')))
       $quarters["February"][] = $formatteddate;

    else if(in_array($donor_month, array('03')))
       $quarters["March"][] = $formatteddate;

    else if(in_array($donor_month, array('04')))
       $quarters["April"][] = $formatteddate;

    else if(in_array($donor_month, array('05')))
       $quarters["May"][] = $formatteddate;

    else if(in_array($donor_month, array('06')))
       $quarters["June"][] = $formatteddate;

    else if(in_array($donor_month, array('07')))
       $quarters["July"][] = $formatteddate;

    else if(in_array($donor_month, array('08')))
       $quarters["August"][] = $formatteddate;

    else if(in_array($donor_month, array('09')))
       $quarters["September"][] = $formatteddate;

    else if(in_array($donor_month, array('10')))
       $quarters["Ocotber"][] = $formatteddate;

    else if(in_array($donor_month, array('11')))
       $quarters["November"][] = $formatteddate;

    else if(in_array($donor_month, array('12')))
       $quarters["December"][] = $formatteddate;
}

 /* now go through your array and display the results */
 foreach ($quarters as $quartername => $quarter){
     /* $quarters won't have any entry for quarters with no dates, so technically this 'if' isn't needed,
       however I've added it in case it will be needed it for any other changes you make */
     if ($quarter){ ?>

         <h3><?php echo $quartername; ?></h3>
         <table>
         <?php  foreach ($quarter as $qdate ){ ?>
             <tr><td> <?php echo $qdate; ?> </td></tr>
         <?php  }  // end foreach($quarter...) ?>
         </table>
     <?php
     } // end if
} // end foreach($quarters...)
?>

现在我得到这样的结果:

十月

  • 02/10/2018
  • 29/10/2017

一月

  • 02/01/2018

十二月

  • 2017 年 2 月 12 日
  • 2017 年 1 月 12 日

五月

  • 02/05/2018

...

订单基于发布日期,而不是基于自定义字段。 年份之间也没有区别。 2017 年应该有它自己的循环,就像 2018 年一样。

如果我尝试将自己的数组放在循环的第一个数组中,它没有任何效果,它只会在前端显示为文本。

编辑:我可以使用这样的自定义查询来订购月份:

$posts = query_posts( array(
    'post_type' => 'event',
    'meta_key' => 'event_date',
    'meta_compare' => '>=',
    'meta_value' => $current_date_query,
    'post_status' => 'publish',
    'posts_per_page' => '99',
    'orderby' => 'meta_value',
    'order' => 'ASC',
    'paged' => $paged
) );

现在的问题只是年份。都是按月排序的,每个月都有不同的年份。

【问题讨论】:

标签: php wordpress wordpress-theming


【解决方案1】:

您可以将当前循环月份存储在一个变量中,并检查您是否仍在同一月份循环。

假设$events 是一个数组,其中包含您要显示为WP_Post 实例的所有事件。

$current = 0;

foreach($events as $event){

    $eventDate = get_field('event_date', $event->ID);
    $month = date('m', strtotime($eventDate));

    // New month
    if($current != $month){
        $current = $month;
        // Perform actions of new month
    }

    // Perform normal actions for the event

}

【讨论】:

  • 非常感谢您的快速响应!但我不知道如何将您的代码添加到我的查询中:-(
【解决方案2】:

您从@FluffyKitten 尝试的解决方案无法正常工作,因为它分组为同一月份的组,而不是同一月份和同一年份,因此当不同年份的同一月份有帖子时会崩溃

正如@ChinLeung 建议的那样,您需要将当前月份存储在一个变量中,以测试它何时发生变化并输出您的标题。要为您的示例实现这一点,您将执行以下操作:

// Set current month
$current_month = '';

// Get event posts in order
$events = query_posts( array(
    'post_type' => 'event',
    'meta_key' => 'event_date',
    'meta_compare' => '>=',
    'meta_value' => date ('Y-m-d'),
    'meta_type'  => 'DATE',
    'post_status' => 'publish',
    'posts_per_page' => '99',
    'orderby' => 'meta_value',
    'order' => 'ASC',
    'paged' => $paged
) );

// Iterate over events
foreach($events as $key => $event){

  // Get event date from post meta
  $event_date = get_post_meta($event->ID, 'event_date', $single = true);

  // Cache event month/year
  $event_month = date('F Y', strtotime($event_date));

  // Open new group if new month
  if($current_month != $event_month){
    if($key !== 0) echo '</ul>';  
    echo "<h2>{$event_month}</h2>";
    echo '<ul>';  
  }     

  // Add event date as new list item
  echo "<li>{$event_date}</li>";

  // Cache $curret_month
  $current_month = $event_month;        
}

// Close the last list if query had events
if(count($events)) echo '</ul>';

编辑

要更新此解决方案以适用于帖子类型存档,请将以下内容添加到主题的 functions.php 或其中包含的文件中:

/**
 * Get event date 
 *
 * @return string
 */
function get_event_date() {

    /** @global WP_Post $post */
    global $post;

    /** Get event date from post meta */
    return get_post_meta($post->ID, 'event_date', $single = true);
}

/**
 * Get event month/year formatted
 *
 * @param string $event_date
 * 
 * @return string
 */
function format_event_date($event_date) {
    return date('F Y', strtotime($event_date));
}

/**
 * Order events archive by event date post meta
 *
 * @param WP_Query $query
 *
 * @return WP_Query
 */
function events_archive_pre_get_posts($query) {
    if (!$query->is_main_query() || !is_post_type_archive('event')) return $query;
    $query->set('meta_key', 'event_date');
    $query->set('meta_compare', '>=');
    $query->set('meta_value', date('Y-m-d'));
    $query->set('meta_type', 'DATE');
    $query->set('posts_per_page', 2);
    $query->set('orderby', 'meta_value');
    $query->set('order', 'ASC');
    return $query;
}

add_filter('pre_get_posts', 'events_archive_pre_get_posts');

然后您可以将每页的帖子设置为所需的数量,并且分页将按预期工作。这是一个示例帖子类型存档模板,可用于在格式整齐的 HTML 列表之间添加日期标题,或者至少在将制表符转换为空格之前是这样:

<?php // Template header
get_header(); ?>


<?php /** @global WP_Query */
global $wp_query; ?>

<?php // Events archive loop
for($previous_month = ''; have_posts(); $previous_month = $formatted_date): the_post();

    // Get event date from post meta
    $event_date = get_event_date();

    // Format event month/year
    $formatted_date = format_event_date($event_date);

    // The formatted date is the first or not the same as previous event
    if($previous_month != $formatted_date):

        // Close previous list if this is not the first
        if($wp_query->current_post !== 0) echo "\n\t</ul>\n"; 

        // New month template ?>
    <h2><?php echo $formatted_date; ?></h2>
<?php
        // Open new list
        echo "\t<ul>\n";
    endif; 

    // Event post template ?>
        <li><?php echo $event_date; ?></li>
<?php endfor;

// Reset query 
wp_reset_query();

// Close the last list if query had events 
if(have_posts()) echo "\t</ul>\n"; ?>


<?php // Pagination
the_posts_pagination(); ?>


<?php // Template footer
get_footer();

【讨论】:

  • 您好,感谢您的回答。但我不明白。如果我将它粘贴到我的代码中并将 meta_key 更改为我的 meta_key 的名称,它会显示一个空列表。如果我从问题中添加查询,它会显示所有事件日期的列表,并且当月没有标题。而且我也不明白我是如何在我的代码中实现它的,所以我在列表中也有事件数据(标题、链接...)。
  • 谢谢,现在可以了。只有两件事...... 1.
      元素相互打开。结束标签似乎有错误。我想我可以弄清楚。我更大的问题是如何打印活动日期(标题、永久链接、摘录……)。如果我回显标题,它总是对所有事件显示相同。
  • 我发布得太快了,应该先更正我的答案。我看到了数据类型冲突,并认为这是唯一的错误,然后发布后意识到还有其他几个错误,正如您使用嵌套的 &lt;ul&gt; 所描述的那样。我目前没有时间说明为什么原件不起作用,但我已经用经过测试的解决方案更新了我的答案。当我发布评论时,我所做的唯一测试是使用 query_posts() 在全新安装上测试自定义帖子和 var_dump() 正如你所说的那样,它没有返回任何数据,但在我的测试站点上进行了。
  • 如果使用'posts_per_page' =&gt; '99''paged' =&gt; $paged不是为了分页而只是为了获取所有帖子,这两行不是必需的,而是设置'numberposts' =&gt; -1,将防止WP_Query限制查询结果。
  • 我已经删除了一些我的 cmets,因为链接似乎在聊天中继续,因为它们对其他人没有帮助,我已经更新了过滤主查询的答案,而不是使用示例 @ 987654330@ 涵盖两种情况
猜你喜欢
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-29
  • 2013-08-12
  • 1970-01-01
  • 2016-06-10
相关资源
最近更新 更多