web-dev-qa-db-fra.com

compter les messages des termes de taxonomie personnalisés par année

Je souhaite créer des tableaux de type statistique contenant le nombre de messages dans des termes de taxonomie personnalisés et les afficher par année, ainsi que le nombre total de messages de cette année.

Par exemple:

2014

| _Taxonomie Terme A: 8 postes

| _ Taxonomie Terme B: 12 ​​postes

Nombre total de postes en 2014: 20 postes

La fonction doit évidemment faire ce qui suit:

  • compter les messages de mon type personnalisé après leur publication en 2014, 2013, ... (nombre total par an)
  • compter les messages dans chaque terme de taxonomie à partir de ma taxonomie personnalisée sur la base annuelle

Pour faire une liste dynamique pour les années , j’ai utilisé un extrait que j’ai trouvé quelque part et qui ressemble à ceci:

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;
}

Dans mon modèle de page personnalisé, j'utilise:

<?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; ?>

Ma question est la suivante:

Comment est-ce que je construis wp_query pour pouvoir générer le nombre de posts par terme de taxonomie par an? Je serais si heureux si quelqu'un m'aidait à résoudre ce problème.

PS: J'ai déjà un tableau qui compte TOUS les articles publiés de mon type personnalisé par type de taxinomie, j'ai trouvé help ici et utilisé le code de deflime.

Modifier:

Voici l'extrait de Pieter Goosen avec mes modifications:

$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
4
okiedokey

EDIT 2

Voici une autre version du code dans EDIT 1. Ce code est beaucoup plus rapide. Voici mon test entre le code dans EDIT 1et EDIT 2

  • EDIT 1heure d'interrogation de la base de données = +/- 0.25 et interrogations de la base de données = 69

  • EDIT 2temps d'interrogation de base de données = +/- 0.07 et interrogations de base de données = 29

Voici le code

<?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

?>

Cela donne le même résultat que le tableau dans EDIT 1, sauf qu'il ne montre pas les termes vides, seuls les termes avec posts sont affichés

enter image description here

EDIT 1

De votre question modifiée, voici la bande du nouveau code. J'ai dû supprimer une ou deux choses ici et réorganiser certains éléments pour que cela fonctionne. Le grand défi consistait à calculer les pourcentages, car les variables utilisées pour le calculer vivaient dans des boucles foreachdistinctes. Les variables contenues dans les boucles foreachne vivent que dans cette foreachname__, et non pas dans le dehors

Les gros changements apportés au code (à partir de ma réponse originale, le code @deflime et votre code intégré) depuis votre édition sont:

  • Déplacement des deux tables contenant le nombre total d'articles et les pourcentages et les noms de termes à l'extérieur juste en dessous de la boucle $termsforeachname__

  • Déplacement des noms de terme et des posts de chaque terme dans un tableau situé en dehors de la boucle $termsforeachname__

  • Code @deflime mis au rebut, supprimé $total_posts = 0; et uniquement conservé et modifié $percentage = round( (($yearly_posts_per_term->post_count / $total_posts)*100), 2 );

  • Utilisé array_sum pour obtenir le nombre total de publications pour l'année à partir du tableau de décompte de publications par session

  • Utilisé array_combine pour créer un tableau associatif avec les noms de termes et comptabiliser les comptes de chaque terme

  • Enfin, j'ai utilisé une boucle foreachpour obtenir chaque nom de terme et le nombre de publications associé, afin de les intégrer dans la table.

Voici le code 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

?>

Veuillez noterComme dans ma réponse d'origine, j'ai modifié le type de publication en postet la taxonomie en categoryà des fins de test.

Votre résultat final est une table ressemblant à ceci. Veuillez notertous les noms de mes termes sont en afrikaans comme je les ai testés sur mon site de test en afrikaans.

enter image description here

RÉPONSE ORIGINALE

C'est un brouillon d'une idée que j'avais sur la façon de procéder. Je n'ai inclus aucune balise HTML et utilisé le type de publication par défaut postet la taxonomie intégrée categorypour tester le code.

Voici comment j'ai construit la requête complète

  • Tout d’abord, obtenez la date du message le plus ancien (ce devrait être le premier) sur le site. Cela se fait par une simple requête get_posts . Modifier pour répondre à vos besoins

    $oldest = get_posts( 'post_status=publish&posts_per_page=1&order=ASC' );
        $oldest_date = $oldest[0]->post_date;
    
  • Ensuite, supprimez la date renvoyée pour obtenir uniquement l'année à partir de la date de publication. Utilisez la fonction strtotime() pour convertir l'année en horodatage Unix

    $first_date = date('Y', strtotime($oldest_date));
    
  • Renvoyer la date du jour, vous ne voudriez que l'année. Utilisez la fonction date()

    $current_date = date('Y');
    
  • Renvoie les deux dates à la fonction range() pour imprimer une plage d'années entre les deux dates

    $year_range = range($current_date, $first_date);
    
  • Rajoutez ces plages dans un foreach loop pour obtenir vos publications dans des listes basées sur des années.

  • J'ai utilisé get_terms() pour obtenir une liste de tous les termes disponibles de la taxonomie en question

    $terms = get_terms('category');
    
  • Maintenant, toutes ces informations doivent être réintroduites dans un tax_query en utilisant 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);
    
  • Enfin, vous voulez renvoyer le nom du terme et le nombre de messages par terme

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

Maintenant tous ensemble !!

<?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 . ')';
        }
    }
}
 ?>

Comme cela a été dit, cela peut être affiné, alors prenez cette idée et codez-la, adaptez-la et modifiez-la à votre guise. J'espère que cela t'aides.

4
Pieter Goosen

Il existe une solution beaucoup plus simple que celle que vous avez acceptée, en utilisant une seule requête. J'illustre ici le type d'article personnalisé 'product' et la taxonomie personnalisée 'product_cat' (egory) dans Woocommerce, simplement parce que je dispose d'une installation pratique pour le tester. Le $query est:

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

Dans mon exemple d'installation, cela donne:

taxonomy stats per year

Ainsi, par exemple, il y a 10 postes d’habillement en 2013 et 2 en 2012.

Il vous suffit d'appeler $wpdb->get_results($query) (et d'utiliser $ wpdb-> prefix au lieu de 'wp_') pour obtenir cette table dans un tableau ou un objet, calculer les pourcentages et les afficher. Les colonnes group_concat sont ajoutées principalement pour le débogage (par conséquent, vous voudrez probablement les supprimer), mais d'un autre côté, l'id peut aussi être utile pour un autre traitement (en décomposant les valeurs de la colonne dans des tableaux).

1
adelval

Dans le cas où quelqu'un recherche un code plus simple et plus simple pour afficher uniquement une année spécifique au lieu d'exécuter une boucle pour afficher toutes les années à compter de la publication. C'est le code  enter image description here  .

Cela inclut également un lien vers l'archive des termes de taxonomie. `

    $terms = get_terms('your-taxonomy'); //grab the taxonomy name
    $year  = 2015; // The year you want to pull the terms and count from

    if ( !empty( $terms ) && !is_wp_error( $terms ) ){ 
    echo '<div class="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>';          
} 

`

0
icynets