contar publicaciones de términos de taxonomía personalizados por año

4

Quiero crear tablas similares a estadísticas con el recuento de publicaciones en términos de taxonomía personalizados dados y mostrarlas por año junto con el recuento total de publicaciones de ese año.

Por ejemplo:

  

2014

     

| _Taxonomy Término A: 8 publicaciones

     

| _ Taxonomy Term B: 12 posts

     

Total de publicaciones en 2014: 20 publicaciones

La función obviamente necesita hacer lo siguiente:

  • cuenta las publicaciones de my-custom-post-type que se publicaron en 2014, 2013, ... (recuento total por año)
  • cuente las publicaciones en cada término de taxonomía de my-custom-taxonomy en la base anual

Para hacer una lista dinámica para los años , utilicé un fragmento de código que encontré en algún lugar y se ve así:

function posts_by_year() {
  // array to use for results
  $years = array();

  // get posts from WP
  $posts = get_posts(array(
    'numberposts' => -1,
    'orderby' => 'post_date',
    'order' => 'ASC',
    'post_type' => 'my-custom-post-type',
    'post_status' => 'publish'
  ));

  // loop through posts, populating $years arrays
  foreach($posts as $post) {
    $years[date('Y', strtotime($post->post_date))][] = $post;
  }

  // reverse sort by year
  krsort($years);
  return $years;
}

En mi plantilla de página personalizada, uso:

<?php foreach(posts_by_year() as $year => $posts) : ?>
<h2><?php echo $year; ?></h2>
// the code that I need to display the post counts per year
<?php endforeach; ?>

Mi pregunta es:

¿Cómo compilo wp_query para poder generar el recuento de publicaciones por término de taxonomía por año? Me alegraría mucho que alguien me ayudara a resolverlo.

PS: Ya tengo una tabla contando TODAS las publicaciones publicadas de my-custom-post-type por término de taxonomía, encontré ayuda aquí y usé el código de tiempo de ejecución.

Editar:

Este es el fragmento de Pieter Goosen que incluye mis modificaciones:

$oldest = get_posts( 'post_type=my-custom-post-type&post_status=publish&posts_per_page=1&order=ASC' );
$oldest_date = $oldest[0]->post_date;

$first_date = date('Y', strtotime($oldest_date));
$todays_date = date('Y');

$year_range = range($todays_date, $first_date);

foreach ($year_range as $year) { // dynamic year-based tables
    echo '<h2>' . $year . '</h2>';
    $terms = get_terms('my-custom-taxonomy');
    $total_posts = 0;

    if ( !empty( $terms ) && !is_wp_error( $terms ) ) { // table body

        echo '
            <table class="statistics">
            <tbody>
            ';
        echo '
            <thead>
                <tr>
                    <td>Taxonomy Term</td>
                    <td>Percentage</td>
                    <td class="chart-count">Count</td>
                </tr>
            </thead>
            ';
        echo '
            <tfoot>
                <tr>
                <td colspan="2">Posts total</td>
                <td class="chart-count">'.$total_posts.'</td>
                </tr>
            </tfoot>
            ';

        foreach ( $terms as $term ) { // setup table <tr> per taxonomy term
            $args = array(
                'posts_per_page'    => -1,
                'post_type'         => 'my-custom-post-type',
                'post_status'       => 'publish',
                'year'              => $year,
                'tax_query' => array(
                    array(
                        'taxonomy' => 'my-custom-taxonomy',
                        'field'    => 'slug',
                        'terms'    => $term->slug
                    ),
                ),
            );

            $total_posts += $term->count;
            // Get  %, round to 2 decimal places
            $percentage = round( (($yearly_posts_per_term->post_count / $total_posts)*100), 2 );
            // will add up to 100 at the end?
            $total_check += $percentage;

            $yearly_posts_per_term = new WP_Query($args);

            echo '
                <tr>
                    <td class="chart-item">'.$term->name.'</td>
                    <td class="chart-visual"><div class="chart-bar" style="width:'.$percentage.'%;"></div> '.$percentage.'%</td>
                    <td class="chart-count">'.$yearly_posts_per_term->post_count.'</td>
                </tr>
            ';

        } // endforeach
        echo '
            </tbody>
            </table>
            '; 
    } //end of table
} // end of year-based list
    
pregunta okiedokey 11.08.2014 - 11:58

3 respuestas

4

EDIT 2

Aquí hay otra versión del código en EDIT 1 . Este código es mucho más rápido. Aquí está mi prueba entre el código en EDIT 1 y EDIT 2

  • EDIT 1 Tiempo de consulta de la base de datos = +/- 0.25 y Consultas de la base de datos = 69

  • EDIT 2 Tiempo de consulta de la base de datos = +/- 0.07 y Consultas de la base de datos = 29

Aquí está el código

<?php

 $oldest = get_posts( 'post_type=post&post_status=publish&posts_per_page=1&order=ASC' );
    $oldest_date = $oldest[0]->post_date;

    $first_date = date('Y', strtotime($oldest_date));
    $todays_date = date('Y');

    $year_range = range($todays_date, $first_date);

    foreach ($year_range as $year) { // dynamic year-based tables
        echo '<h2>' . $year . '</h2>';
        $terms = get_terms('category');

        $term_slugs = array();

        if ( !empty( $terms ) && !is_wp_error( $terms ) ) { // table body

            foreach ( $terms as $key=>$term){
                $term_slugs[$key] = $term->slug;
            }

            echo '
                <table class="statistics">
                <tbody>
                ';
            echo '
                <thead>
                    <tr>
                        <td>Taxonomy Term</td>
                        <td>Percentage</td>
                        <td class="chart-count">Count</td>
                    </tr>
                </thead>
                ';

            $posts_count = array(); // Holds all term post counts in an array
            $terms_array = array();  // Holds all term names in an array 

                $args = array(
                    'posts_per_page'    => -1,
                    'post_type'         => 'post',
                    'post_status'       => 'publish',
                    'year'              => $year,
                    'tax_query' => array(
                        array(
                            'taxonomy'          => 'category',
                            'field'             => 'slug',
                            'terms'             => $term_slugs,
                            'include_children'  => false 
                        ),
                    ),
                );

                $yearly_posts_per_term = new WP_Query($args);
                    $posts_count[] = $yearly_posts_per_term->post_count; //Collects post counts and send them to an array

                if($yearly_posts_per_term->have_posts()):
                    while($yearly_posts_per_term->have_posts()): $yearly_posts_per_term->the_post();

                        $terms = get_the_terms( $post->ID, 'category' );

                        if ( $terms && ! is_wp_error( $terms ) ) {
                            foreach ( $terms as $term ) {
                                $terms_array[] = $term->slug;
                            }
                        } 

                    endwhile;
                endif;

        }

        $total_posts = array_sum($posts_count); //Use array_sum to add up all the separate post counts

        $result = array_count_values($terms_array);

        foreach ($result as $term_name=>$count) {

            $percentage = round( (($count / $total_posts)*100), 2 ); //Calculate the percentages of each term post cound to total year post count

            echo '
                    <tr>
                        <td class="chart-item">'.$term_name.'</td>
                        <td class="chart-visual"><div class="chart-bar" style="width:'.$percentage.'%;"></div> '.$percentage.'%</td>
                        <td class="chart-count">'.$count.'</td>
                    </tr>
                ';
        }   

            echo '
                <tfoot>
                    <tr>
                    <td colspan="2">Posts total</td>
                    <td class="chart-count">'.$total_posts.'</td>
                    </tr>
                </tfoot>
                ';

            echo '
                </tbody>
                </table>
                '; 
    } // end of year-based list

?>

Esto representa la misma salida que la tabla en EDIT 1 , excepto que no muestra términos vacíos, solo se muestran los términos con publicaciones

EDIT1

Apartirdesupreguntaeditada,aquíestálalistadesplegabledelnuevocódigo.Tuvequedesecharunaodoscosasaquíyreorganizaralgunoselementosparaqueestofuncione.Elgrandesafíoaquífuecalcularlosporcentajes,porquelasvariablesqueseutilizanparacalcularestovivíanenbuclesseparadosforeach.Lasvariablesdentrodeforeachloopssolovivendentrodeeseforeach,nooutsie

Losgrandescambiosenelcódigo(demirespuestaoriginal,@deflimecodeytucódigointegrado)detuediciónson

  • Moviólasdostablasquetienenelrecuentototaldepublicacionesylosporcentajesylosnombresdelostérminosalexteriorjustodebajodel$termsforeachloop

  • Eltérminodelosnombresylaspublicacionesdecadatérminoseubicóenunamatrizfueradel$termsforeachloop

  • Seeliminóelcódigo@deflime,seeliminó$total_posts=0;ysoloseconservóysemodificó$percentage=round((($yearly_posts_per_term->post_count/$total_posts)*100),2);

  • Usé array_sum para obtener la cantidad total de publicaciones para el año de la matriz de cuentas por publicación

  • Usé array_combine para crear una matriz asociativa con el término nombres y contadores de publicaciones de cada término

  • Finalmente, utilicé un bucle foreach para obtener el nombre de cada término y el recuento de publicaciones asociado, para devolver eso a la tabla

Aquí está el código final

<?php

 $oldest = get_posts( 'post_type=post&post_status=publish&posts_per_page=1&order=ASC' );
    $oldest_date = $oldest[0]->post_date;

    $first_date = date('Y', strtotime($oldest_date));
    $todays_date = date('Y');

    $year_range = range($todays_date, $first_date);

    foreach ($year_range as $year) { // dynamic year-based tables
        echo '<h2>' . $year . '</h2>';
        $terms = get_terms('category');

        if ( !empty( $terms ) && !is_wp_error( $terms ) ) { // table body

            echo '
                <table class="statistics">
                <tbody>
                ';
            echo '
                <thead>
                    <tr>
                        <td>Taxonomy Term</td>
                        <td>Percentage</td>
                        <td class="chart-count">Count</td>
                    </tr>
                </thead>
                ';

            $posts_count = array(); // Holds all term post counts in an array
            $term_names = array();  // Holds all term names in an array

            foreach($terms as $term) {
                $term_names[] = $term->name; //Collects term names and send them to an array

                $args = array(
                    'posts_per_page'    => -1,
                    'post_type'         => 'post',
                    'post_status'       => 'publish',
                    'year'              => $year,
                    'tax_query' => array(
                        array(
                            'taxonomy'          => 'category',
                            'field'             => 'slug',
                            'terms'             => $term->slug,
                            'include_children'  => false 
                        ),
                    ),
                );

                $yearly_posts_per_term = new WP_Query($args);
                    $posts_count[] = $yearly_posts_per_term->post_count; //Collects post counts and send them to an array

            } // endforeach

            unset($term);

        }

        $total_posts = array_sum($posts_count); //Use array_sum to add up all the separate post counts

        $combine = array_combine($term_names,$posts_count); //Use array_combine to combine term names and post counts into assosiative array

        foreach ($combine as $term_name=>$count) {

            $percentage = round( (($count / $total_posts)*100), 2 ); //Calculate the percentages of each term post cound to total year post count

            echo '
                    <tr>
                        <td class="chart-item">'.$term_name.'</td>
                        <td class="chart-visual"><div class="chart-bar" style="width:'.$percentage.'%;"></div> '.$percentage.'%</td>
                        <td class="chart-count">'.$count.'</td>
                    </tr>
                ';
        }   

            echo '
                <tfoot>
                    <tr>
                    <td colspan="2">Posts total</td>
                    <td class="chart-count">'.$total_posts.'</td>
                    </tr>
                </tfoot>
                ';

            echo '
                </tbody>
                </table>
                '; 
    } // end of year-based list

?>

Tenga en cuenta Al igual que en mi respuesta original, cambié el tipo de publicación a post y la taxonomía a category con el fin de realizar pruebas.

Tu resultado final es una tabla con este aspecto. Tenga en cuenta Todos los nombres de mis términos están en afrikaans tal como lo probé en mi sitio de prueba que está en afrikaans.

RESPUESTAORIGINAL

Esteesunborradordeunaideaquetuvesobrecómohaceresto.NoheincluidoningúnmarcadoHTMLyutilicéeltipodepublicaciónpredeterminadopostylataxonomíaincorporadacategoryparaprobarelcódigo.

Aquíescómoconstruílaconsultacompleta

  • Primero,obtengalafechadelapublicaciónmásantigua(debeserlaprimerapublicación)enelsitio.Estosehacemedianteunaconsultasimple get_posts . Modificar para adaptarse a sus necesidades

    $oldest = get_posts( 'post_status=publish&posts_per_page=1&order=ASC' );
        $oldest_date = $oldest[0]->post_date;
    
  • A continuación, elimine la fecha devuelta para obtener solo el año a partir de la fecha de envío. Use la función strtotime() para convertir el año en una marca de tiempo Unix

    $first_date = date('Y', strtotime($oldest_date));
    
  • Devuelve la fecha actual, solo querrías el año. Utilice la función date()

    $current_date = date('Y');
    
  • Regrese ambas fechas a la función range() para imprimir un rango de años entre las dos fechas

    $year_range = range($current_date, $first_date);
    
  • Vuelva a agregar estos rangos a foreach loop para obtener sus publicaciones en listas basadas en el año

  • He usado get_terms() para obtener una lista de todos los términos disponibles de la taxonomía en cuestión

    $terms = get_terms('category');
    
  • Ahora, toda esta información debe ser devuelta a tax_query usando WP_Query

    $args = array(
            'posts_per_page'    => -1,
            'post_type'         => 'post',
            'post_status'       => 'publish',
            'year'              => $year,
            'tax_query' => array(
                array(
                    'taxonomy' => 'category',
                    'field'    => 'slug',
                    'terms'    => $term->slug
                ),
            ),
        );
    
    $posts = new WP_Query($args);
    
  • Por último, desea devolver el nombre del término y la cantidad de publicaciones por término

    echo $term->name . '(' . $posts->post_count . ')';
    

¡¡Ahora todos juntos !!

<?php
$oldest = get_posts( 'post_status=publish&posts_per_page=1&order=ASC' );
    $oldest_date = $oldest[0]->post_date;

$first_date = date('Y', strtotime($oldest_date));
$current_date = date('Y');

$year_range = range($current_date, $first_date);

foreach ($year_range as $year) {
    echo $year;

    $terms = get_terms('category');
    if ( !empty( $terms ) && !is_wp_error( $terms ) ){

        foreach ( $terms as $term ) {
            $args = array(
                'posts_per_page'    => -1,
                'post_type'         => 'post',
                'post_status'       => 'publish',
                'year'              => $year,
                'tax_query' => array(
                    array(
                        'taxonomy' => 'category',
                        'field'    => 'slug',
                        'terms'    => $term->slug
                    ),
                ),
            );

            $posts = new WP_Query($args);

                echo $term->name . '(' . $posts->post_count . ')';
        }
    }
}
 ?>

Como se dijo, esto puede ser refinado, así que toma esta idea y codifica y adapta y modifica como mejor te parezca. Espero que esto ayude.

    
respondido por el Pieter Goosen 11.08.2014 - 21:22
1

Hay una solución mucho más simple que la que aceptaste, usando solo una consulta. Ilustro aquí para el tipo de producto personalizado 'producto' y la taxonomía personalizada 'producto_cat' (egory) en Woocommerce, solo porque tengo una instalación útil para probarlo. El $query es:

SELECT YEAR(p.post_date), t.name, COUNT(*), GROUP_CONCAT(p.ID), GROUP_CONCAT(p.post_title)
FROM wp_posts p
JOIN wp_term_relationships tr ON p.ID = tr.object_id
JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms t ON tt.term_id = t.term_id
WHERE tt.taxonomy = 'product_cat' AND p.post_type = 'product' AND p.post_status='publish'
GROUP BY YEAR(p.post_date), tt.term_taxonomy_id
ORDER by YEAR(p.post_date) DESC, tt.term_taxonomy_id ASC

En mi instalación de muestra, esto produce:

Entonces, por ejemplo, hay 10 publicaciones de Ropa en 2013 y 2 en 2012.

Solo necesita llamar a $wpdb->get_results($query) (y usar $ wpdb- > prefijo en lugar de 'wp_') para obtener esta tabla en una matriz u objeto, calcular los porcentajes y mostrarlos. Las columnas group_concat se agregan principalmente para la depuración (por lo tanto, es probable que desee eliminarlas), aunque, por otro lado, los identificadores, por ejemplo, también pueden ser útiles para otro procesamiento (haciendo explotar los valores de la columna en matrices).

    
respondido por el adelval 17.08.2014 - 16:30
0

En caso de que alguien esté buscando un código más corto y más fácil para mostrar solo un año específico en lugar de ejecutar un ciclo para mostrar todos los años desde la publicación. Este es el código .

Estotambiénincluyeunenlacealarchivodetérminosdetaxonomía.'

$terms=get_terms('your-taxonomy');//grabthetaxonomyname$year=2015;//Theyearyouwanttopullthetermsandcountfromif(!empty($terms)&&!is_wp_error($terms)){echo'<divclass="barometer">'; //class to apply css if you want
        echo '<ul>'; 

            foreach ( $terms as $term ) { 
                $args = array(
            //'posts_per_page'    => -1,
            'post_type'         => 'post', // disable this line if you want to grap from all post types
            'post_status'       => 'publish',
            'year'              => $year,
            'tax_query' => array(
                array(
                    'taxonomy' => 'your-taxonomy',
                    'field'    => 'slug',
                    'terms'    => $term->slug
                    ),
                ),
            );

            $post_year = new WP_Query($args); 

                $term = sanitize_term( $term, 'your-taxonomy' ); 
                $term_link = get_term_link( $term, 'your-taxonomy' ); //Get the links to the term archive page

        // If the term has no post, it does not display. You can remove the if statement from here if you want to display empty terms   
        if ($post_year->post_count > 0 ) {

            echo '<li><a href="' . esc_url( $term_link ) .'" title="' . sprintf( __( 'View all %s stories','media-foundation' ), $term->name ) . '">' . $term->name . '<span>' .$post_year->post_count. '</span>' . '</a></li>'; 

        } // End of if $post_year->post_count

    } // End of Foreach term loop
        echo '</ul>';
    echo '</div>';          
} 

'

    
respondido por el icyNETS 20.11.2015 - 21:59

Lea otras preguntas en las etiquetas