web-dev-qa-db-ja.com

カスタム分類学用語からの投稿数を年ごとに数える

私は与えられたカスタム分類学用語の中の投稿の数で統計のような表を作り、その年からの総投稿数と共に年ごとにそれらを表示したいです。

例えば:

2014

| _分類学用語A:8件の投稿

| _分類学用語B:12件の投稿

2014年の総投稿数: 20の投稿

この関数は明らかに以下のことをする必要があります。

  • 2014年、2013年に公開されたmy-custom-post-typeからの投稿数を数える(年間合計数)
  • my-custom-taxonomyの各分類用語の投稿数を年間ベースで数えます。

年の動的リストを作るために 、私はどこかで見つけたスニペットを使いました、そしてそれはこのように見えます:

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

私のカスタムページテンプレートでは、

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

私の質問です:

年ごとの分類期間ごとの投稿数を出力できるようにwp_queryを作成する方法を教えてください。誰かが私がそれを整理するのを手伝ってくれたら私はとてもうれしいです。

シモンズ:私はすでに分類学用語ごとの私のカスタムポストタイプからのすべての公開されたポストを数えるテーブルを持っています、私は助けを見つけました ここ そしてdeflimeのコードを使いました。

編集:

これは私の修正を含むPieter Goosenのスニペットです:

$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

編集2

これはEDIT 1のコードの別のバージョンです。このコードはもっとずっと速いです。これがEDIT 1EDIT 2のコードの間のテストです。

  • EDIT 1データベースクエリ時間= +/- 0.25およびデータベースクエリ= 69

  • 編集2データベースクエリ時間= +/- 0.07およびデータベースクエリ= 29

これがコードです

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

?>

これはEDIT 1の表と同じ出力を表示しますが、空の用語は表示されず、投稿のある用語のみが表示されます。

enter image description here

編集1

編集した質問から、これが新しいコードの削除です。私はここで1つか2つのことをスクラップし、この仕事をするためにいくつかの要素を並べ替える必要がありました。ここでの大きな課題は、パーセンテージを計算することでした。これを計算するために使用される変数は別々のforeachループに存在していたからです。 foreachループ内の変数はそのforeach内にのみ存在し、outsieには存在しません。

あなたの編集からの(私の最初の答え、@deflimeコードとあなたの統合されたコードからの)コードへの大きな変更はあります。

  • 総投稿数と割合と用語名を保持する2つのテーブルを$termsforeachループのすぐ下の外側に移動しました

  • 用語名と投稿数を各用語から$termsforeachループの外側の配列にプッシュしました

  • @deflimeコードを破棄し、$total_posts = 0;を削除し、$percentage = round( (($yearly_posts_per_term->post_count / $total_posts)*100), 2 );のみを保持および変更しました

  • 期間ごとの投稿数の配列から、その年の投稿の総数を取得するために array_sum を使用しました

  • array_combine を使用して、用語名と各用語の投稿数を含む連想配列を作成しました。

  • 最後に、foreachループを使用して各用語名と関連する投稿数を取得し、それをテーブルにフィードバックしました。

これが最終的なコードです。

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

?>

注意してください私の最初の答えのように、私はテストの目的のために投稿タイプをpostに、分類法をcategoryに変更しました。

あなたの最終結果はこのように見えるテーブルです。 注意してください私はアフリカーンス語にある私のテストサイトでそれをテストしたので私の名前はすべてアフリカーンス語にあります。

enter image description here

元の答え

これは私がこれを行う方法について私が持っていたアイデアの非常に大まかなドラフトです。私はHTMLマークアップを含めず、コードをテストするためにデフォルトの投稿タイプpostとビルトイン分類法categoryを使いました。

これが私が完全なクエリを構築した方法です。

  • まず、サイト上で最も古い投稿の日付を取得します(最初の投稿になります)。これは単純な get_posts クエリによって行われます。ニーズに合わせて変更する

    $oldest = get_posts( 'post_status=publish&posts_per_page=1&order=ASC' );
        $oldest_date = $oldest[0]->post_date;
    
  • 次に、投稿日から年のみを取得するように返された日付を取り除きます。 strtotime() 関数を使用して年をUnixタイムスタンプに変換します

    $first_date = date('Y', strtotime($oldest_date));
    
  • 現在の日付を返します、あなたは年だけが欲しいでしょう。 date() 関数を使う

    $current_date = date('Y');
    
  • 2つの日付の間の年の範囲を印刷するには、両方の日付を range() 関数に返します。

    $year_range = range($current_date, $first_date);
    
  • これらの範囲をforeach loopに追加して、投稿を年間ベースのリストに入れます。

  • 私は get_terms() を使って、問題の分類法の利用可能なすべての用語のリストを得ました。

    $terms = get_terms('category');
    
  • さて、この情報はすべて tax_query を使って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);
    
  • 最後に、用語名と1用語あたりの投稿数を返します。

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

今、全部一緒に!

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

すでに述べたように、これは洗練されたものになる可能性があるので、このアイデアとコードを取り入れて、必要に応じて調整および変更します。お役に立てれば。

4
Pieter Goosen

1つのクエリだけを使用して、あなたが受け入れたものよりもはるかに簡単な解決策があります。ここでは、私がたまたまそれをテストするのに便利なインストールがあるという理由だけで、Woocommerceのカスタム投稿タイプ 'product'とカスタム分類法 'product_cat'(egory)について説明します。 $queryは次のとおりです。

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

私のサンプルインストールでは、これは次のようになります。

taxonomy stats per year

そのため、たとえば、2013年には10の投稿、2012年には2の投稿があります。

このテーブルを配列またはオブジェクトにしてパーセンテージを計算して表示するには、$wpdb->get_results($query)を呼び出して(そして 'wp_'の代わりに$ wpdb-> prefixを使用するだけ)必要があります。 group_concat列は主にデバッグのために追加されます(したがって、おそらく削除する必要があります)が、idなどの他の処理にも便利です(列の値を配列に展開することによって)。

1
adelval

投稿からすべての年を表示するためのループを実行する代わりに、誰かが特定の年だけを表示するためのより簡単で短いコードを探している場合。これはコードです enter image description here 

これは分類学用語アーカイブへのリンクも含みます。 `

    $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