Exibir postagens por mês

3

Eu quero alcançar algo assim, não sei se é possível e qual seria a melhor maneira de fazer isso:

Amaneiracomoeuprocuroaspostagenséassim:

<divclass="post">
    <?php global $wp_query;
    query_posts( array('post_type' => array( 'lecturas-post' ),'showposts' => 15, 'paged'=>$paged, 'order' => 'DESC' ));?>
    <?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
        <div><?php the_title() ?></a>
    <?php endwhile; // end of the loop. ?>
</div>

Alguém pode me dar uma dica de como ou melhor maneira de fazer isso?

    
por wpuser 27.01.2015 / 10:52

3 respostas

9

Como dito em um comentário, você pode fazer isso em uma consulta. O princípio aqui é exibir apenas o título da data se o mês da postagem anterior não coincide com o da postagem anterior

POUCAS NOTAS

Antes de começar, algumas notas:

  • Nunca use query_posts , exceto se você realmente precisar quebrar tudo em uma página. Ele não apenas reexecuta a consulta principal e também a quebra, atrapalha a paginação e seus globais e também mexe com as funções de objeto consultadas. Se você realmente tiver que executar uma consulta personalizada, use WP_Query ou get_posts

  • showposts foi descartado anos atrás em favor de posts_per_page

  • Não há necessidade de usar o global $wp_query . query_posts confunde mesmo assim

O PLANO

As postagens são exibidas em ordem cronológica com o post mais recente primeiro e o post mais antigo por último, portanto, eles já estão na ordem correta. É apenas uma questão de exibir a data no local apropriado.

Para fazer isso, tudo o que você precisa fazer é obter o mês e o ano atuais da data de postagem da postagem atual e compará-la com o mês da data da postagem da postagem anterior e exibir a data se os meses não combinar ou não exibi-lo se corresponderem

Como explicação, usarei o loop principal com a consulta principal.

Para conseguir isso, você precisa:

  • Obtenha o mês da data de postagem da postagem atual. Para conseguir isso, use get_the_date( 'F' )

  • Coloque a postagem anterior no loop com $wp_query->posts['this will be current post -1 ']->post .

  • Obtenha e compare os meses entre as duas postagens

  • Exibir ou não exibir a data de acordo com a comparação

O CÓDIGO

Este código entra no seu loop, logo após a instrução while() .

$current_month = get_the_date('F');

if( $wp_query->current_post === 0 ) { 

   the_date( 'F Y' );

}else{ 

    $f = $wp_query->current_post - 1;       
    $old_date =   mysql2date( 'F', $wp_query->posts[$f]->post_date ); 

    if($current_month != $old_date) {

        the_date( 'F Y' );;

    }

}

CONSULTA PERSONALIZADA

Se você precisar executar uma consulta personalizada, tente isso

$q = new WP_Query( array('post_type' => array( 'lecturas-post' ),'posts_per_page' => 15, 'paged'=>$paged, 'order' => 'DESC' ));

if( $q->have_posts() ) {
    while( $q->have_posts() ) {

        $q->the_post();

        $current_month = get_the_date('F');

        if( $q->current_post === 0 ) { 

           the_date( 'F Y' );

        }else{ 

            $f = $q->current_post - 1;       
            $old_date =   mysql2date( 'F', $q->posts[$f]->post_date ); 

            if($current_month != $old_date) {

                the_date( 'F Y' );;

            }

        }

        the_title();

    }

}
    
por Pieter Goosen 27.01.2015 / 15:44
4

Resposta atualizada

Depois de pensar no comentário do @PieterGoosen abaixo, adicionei um método para atingir o objetivo do usuário usando uma única consulta.

Aferi os métodos e a consulta única é mais rápida, com o método de consulta múltipla sendo cerca de 15% mais lento . Não é uma boa margem, mas cada pequena ajuda, e para ser honesto, o método provavelmente pode ser mais refinado.

Deixei o método de várias consultas na resposta para prosperidade, mas recomendo que o método de consulta única seja usado.

Método de consulta única

$time_start = microtime(true);

/** Set up a date interval object for 6 monts ago (you can change as required) */
$interval = new DateInterval('P6M');
$interval->invert = 1;

/** Grab the date as it was 6 months ago */
$date = new DateTime(date('Y-m-d'));
$date->add($interval);

/** Query the database for all posts newer than the the given date interval */
$args = array(
    'nopaging'          => true,
    'posts_per_page'    => -1,
    'post_type'         => 'post',
    'post_status'       => 'publish',
    'order_by'          => 'date',
    'date_query'        => array(
        'after' => $date->format('Y-m-d')
    )
);
$month_query = new WP_Query($args);

/** Check to ensure that there are articles for this month... */
if($month_query->have_posts()) :

    $month_titles = array();
    $close_ul = false;


    //echo '<ul style="padding-left: 250px;" id="monthly-posts">';

    /** Set the attributes for displaying the title as an attribute */
    $title_attribute_args = array(
        'before'    => 'Visit article \'',
        'after'     => '\' ',
        'echo'      => false
    );      

    /** Loop through each post for this month... */
    while($month_query->have_posts()) : $month_query->the_post();

        /** Check the month/year of the current post */
        $month_title = date('F Y', strtotime(get_the_date('Y-m-d H:i:s')));

        /** Maybe output a human friendly date, if it's not already been output */
        if(!in_array($month_title, $month_titles)) :

            if($close_ul) echo '</ul>';                                                             // Check if the unordered list of posts should be closed (it shouldn't for the first '$monthe_title')
            echo '<h1 style="padding-left: 250px;" id="monthly-title">' . $month_title . '</h1>';   // Output the '$month_title'
            echo '<ul style="padding-left: 250px;" id="monthly-posts">';                            // Open an unordered lists for the posts that are to come
            $month_titles[] = $month_title;                                                         // Add this '$month_title' to the array of '$month_titles' so that it is not repeated
            $close_ul = true;                                                                       // Indicate that the unordered list should be closed at the next oppurtunity

        endif;

        /** Output each article for this month */
        printf(
            '<li id="monthly-post-%1$s">%2$s <a href="%3$s" title="%4$s">%3$s</a></li>',
            get_the_ID(),                               /** %1$s - The ID of the post */
            get_the_title(),                            /** %2$s - The article title */
            get_permalink(get_the_ID()),                /** %3$s - The article link */
            the_title_attribute($title_attribute_args)  /** %4$s - The title for use as an attribute */
        );

    endwhile;

    if($close_ul) echo '</ul>'; // Close the last unordered list of posts (if there are any shown)

endif;

/** Reset the query so that WP doesn't do funky stuff */
wp_reset_query();

Resposta original

Experimente. Eu configurei para que apenas os últimos 6 meses sejam escolhidos e apenas os últimos 5 posts de cada mês, mas você pode alterar isso como quiser.

Essencialmente, o código primeiro verifica quais meses têm postagens neles e, em seguida, exibe as últimas cinco postagens daquele mês, junto com um link.

Método de consulta múltipla

global $wpdb, $wp_locale;

/** Query the individual months to display (I've chosen the last 6 months) */
$query = $wpdb->prepare('
    SELECT DISTINCT YEAR('%1$s'.'post_date') AS year, MONTH('%1$s'.'post_date') AS month
    FROM '%1$s'
    WHERE '%1$s'.'post_type' = "post"
    ORDER BY '%1$s'.'post_date' DESC
    LIMIT 6',
    $wpdb->posts
);
$months = $wpdb->get_results($query);

/** Count the number of months */
$month_count = count($months);

/** Ensure that there are months to display... */
if($month_count || ($month_count === 1 && $months[0]->month > 0)) :

    /** Loop through each month... */
    foreach($months as $month) :

        if($month->year === 0) :
            continue;
        endif;

        /** Grab the individual month and year, and construct a human friendly date (for the title) */
        $m = zeroise($month->month, 2);
        $y = $month->year;
        $human_date = sprintf(__('%1$s %2$d'), $wp_locale->get_month($m), $y);

        /** Grab any posts for this month (I've chosedn only the last 5 posts) */
        $args = array(
            'nopaging'          => true,
            'posts_per_page'    => 5,
            'post_type'         => 'post',
            'post_status'       => 'publish',
            'order_by'          => 'date',
            'year'              => $y,
            'monthnum'          => $m
        );
        $month_query = new WP_Query($args);

        /** Check to ensure that there are articles for this month... */
        if($month_query->have_posts()) :

            /** Output a human friendly date */
            echo '<h1 id="monthly-title">' . $human_date . '</h1>';
            echo '<ul id="monthly-posts">';

            /** Set the attributes for displaying the title as an attribute */
            $title_attribute_args = array(
                'before'    => 'Visit article \'',
                'after'     => '\' ',
                'echo'      => false
            );      

            /** Loop through each post for this month... */
            while($month_query->have_posts()) : $month_query->the_post();

                /** Output each article for this month */
                printf(
                    '<li id="monthly-post-%1$s">%2$s <a href="%3$s" title="%4$s">%3$s</a></li>',
                    get_the_ID(),                               /** %1$s - The ID of the post */
                    get_the_title(),                            /** %2$s - The article title */
                    get_permalink(get_the_ID()),                /** %3$s - The article link */
                    the_title_attribute($title_attribute_args)  /** %4$s - The title for use as an attribute */
                );

            endwhile;

            echo '</ul>';

        endif;

        /** Reset the query so that WP doesn't do funky stuff */
        wp_reset_query();

    endforeach;

endif;
    
por David Gard 27.01.2015 / 13:29
1

Esta é uma função que utilizei para necessidades gerais, para recuperar dados de postagem ou de tipos de postagem personalizados antes ou depois de um determinado ano / mês ou ano atual, em qualquer ordem que você precisar:

// you could change the name in case it collides with some other plugin
function get_posts_by_date($user_options = array()){

  $options = array(
    'year_limit' => '1980'
    ,'month_limit' => '01'
    ,'operator' => '>=' // date comparison operator
    ,'current_year' => true // limit data to current year
    ,'post_type' => 'post'
    ,'year_order' => 'DESC'
    ,'month_order' => 'DESC'
    ,'post_ids_order' => 'DESC'
    ,'raw_output' => false
  );

  extract(array_merge($options, $user_options));

  global $wpdb;

  if($operator == '>=' || $operator == '=='){
    $day = "01";
  } elseif($mode == '<='){
    $day = "31";
  }

  if($current_year){ // will be after [previous year]/12/31
    $year_limit = date('Y', strtotime('-1 year'));
    $month_limit = '12';
    $day = "31";
    $operator == '>=';
  }

  // warning: if your parameters come from user input/forms, 
  // pass them using $wpdb::prepare()
  // https://developer.wordpress.org/reference/classes/wpdb/prepare/
  $results = $wpdb->get_results("
    SELECT tbl.y year, group_concat(month_posts ORDER BY tbl.m " . $month_order . " SEPARATOR '-') months
      FROM (
        SELECT YEAR(p.post_date) y, MONTH(p.post_date) m, concat(MONTH(p.post_date), ':', group_concat(p.id ORDER BY p.post_date " . $post_ids_order . " )) month_posts
        FROM $wpdb->posts p
        WHERE (p.post_status = 'publish' OR p.post_status = 'future')
          AND p.post_type = '" . $post_type . "'
          AND p.post_date " . $operator . " DATE('" . $year_limit . "-" . $month_limit . "-" . $day . " 00:00:00')
        GROUP BY y, m
      ) tbl
    GROUP BY tbl.y
    ORDER BY tbl.y " . $year_order
  );

  if($raw_output) return $results;

  global $wp_locale;

  foreach ($results as $data){
    $months_data = explode('-',$data->months);
    $months = array();
    $data->count = 0; // year count

    foreach ($months_data as $month_data){
      $month_obj = new stdClass;

      $splitted = explode(':',$month_data);
      $raw_month = $splitted[0];
      $month_obj->number = $raw_month;
      $month_obj->name = $wp_locale->get_month($raw_month);
      $month_obj->posts = array();
      $post_ids = explode(',',$splitted[1]);
      $data->count += count($post_ids);

      foreach($post_ids as $post_id){
        $month_obj->posts[] = get_post($post_id);
        $months[$raw_month] = $month_obj;
      }// foreach
    }// foreach

    $data->months = $months;
  }// foreach

  return $results;
}// get_posts_by_date

Exemplo de uso:

$posts_by_date = get_posts_by_date(array(
  'year_limit' => '2016'
  ,'operator' => '<='
  ,'current_year' => false
  ,'post_type' => 'product'
  ,'month_order' => 'ASC'
  ,'raw_output' => true
));

Se a opção raw_output for verdadeira, a saída padrão será algo assim:

array(2) {
  [0]=>
  object(stdClass)#6645 (2) {
    ["year"]=>
    string(4) "2017"
    ["months"]=>
    string(65) "8:386,401-7:406,373,380,377,408,399,362-6:1,391,404-5:367,397,394"
  }
  [1]=>
  object(stdClass)#6644 (2) {
    ["year"]=>
    string(4) "2016"
    ["months"]=>
    string(5) "6:429"
  }
}

A string "months" contém valores formatados como:

month:[post ids]-month:[post ids]-ecc

Se a opção raw_output for falsa, você receberá uma lista de postagens como esta:

array (array of objects)
  object
    -> year (ex. '2017')
    -> count (total year's posts)
    -> months (array of objects)
        month
          -> number (of month)
          -> name (localized)
          -> posts (array of post objects)

Codificação feliz ...:)

    
por Stratboy 15.08.2017 / 10:59