Hatena::ブログ(Diary)

130単位

2010-06-01

WordPress 日付別アーカイブ一覧をカテゴリー指定可能にするプラグイン 修正編

WordPress 日付別アーカイブ一覧をカテゴリー指定可能にするプラグイン - 130単位

前の記事でプラグインを作ってみましたが、早速不具合が見つかりました。

このような階層化されたカテゴリーがあり、1つの記事で両方のカテゴリーにチェックが付いていると、記事数の表示がおかしくなります。これはフックしている追加のSQL文でGROUP BYしていないのがまずかったです。ただGROUP BYを加えられるようなフックは存在しないため、別の方法で修正してみました。

コード

<?php
/**
 * カテゴリー指定による日付別アーカイブ
 */
Class DateCategoryArchives
{
    public $cat;//カテゴリーを保持

    /**
     * コンストラクタ
     *  メソッドをフックに追加/削除します
     */
    public function __construct() {
        add_filter('getarchives_where', array($this, 'getarchives_where_by_cat'), 10, 2);
        add_filter('year_link', array($this, 'add_cat_query'));
        add_filter('month_link', array($this, 'add_cat_query'));
        add_filter('day_link', array($this, 'add_cat_query'));

        if ($_REQUEST['cat']) {
            remove_filter('template_redirect', 'redirect_canonical');
        }
    }

    /**
     * wp_get_archives()の記事照会のWHERE句にカテゴリーの条件を加えて返します
     *
     * @param     string    $where    WHERE句
     * @param     array     $args    wp_get_archives()の引数をパースした配列
     * @return    string    WHERE句
     */
    public function getarchives_where_by_cat($where, $args) {
        if (!isset($args['cat'])) {
            $this->cat == null;
            return $where;
        }

        global $wpdb;

        //対象とするカテゴリーの抽出
        $q['cat'] = ''.urldecode($args['cat']).'';
        $q['cat'] = addslashes_gpc($q['cat']);
        $cat_array = preg_split('/[,\s]+/', $q['cat']);
        $q['cat'] = '';
        $req_cats = array();
        foreach ( (array) $cat_array as $cat ) {
            $cat = intval($cat);
            $req_cats[] = $cat;
            $in = ($cat > 0);
            $cat = abs($cat);
            if ( $in ) {
                $q['category__in'][] = $cat;
                $q['category__in'] = array_merge($q['category__in'], get_term_children($cat, 'category'));
            } else {
                $q['category__not_in'][] = $cat;
                $q['category__not_in'] = array_merge($q['category__not_in'], get_term_children($cat, 'category'));
            }
        }
        //リクエストするカテゴリーの文字列
        $this->cat = implode(',', $req_cats);;

        //含めるカテゴリー
        if ( !empty($q['category__in']) ) {
            $cat_string = "'" . implode("', '", $q['category__in']) . "'";
            $whichcat .= " AND $wpdb->posts.ID IN ( SELECT dca_n_tr.object_id FROM $wpdb->term_relationships AS dca_n_tr INNER JOIN $wpdb->term_taxonomy AS dca_n_tt ON dca_n_tr.term_taxonomy_id = dca_n_tt.term_taxonomy_id WHERE dca_n_tt.taxonomy = 'category' AND dca_n_tt.term_id IN ($cat_string) )";
        }

        //除外するカテゴリー
        if ( !empty($q['category__not_in']) ) {
            $cat_string = "'" . implode("', '", $q['category__not_in']) . "'";
            $whichcat .= " AND $wpdb->posts.ID NOT IN ( SELECT dca_n_tr.object_id FROM $wpdb->term_relationships AS dca_n_tr INNER JOIN $wpdb->term_taxonomy AS dca_n_tt ON dca_n_tr.term_taxonomy_id = dca_n_tt.term_taxonomy_id WHERE dca_n_tt.taxonomy = 'category' AND dca_n_tt.term_id IN ($cat_string) )";
        }

        return $where . $whichcat;
    }

    /**
     * URLにカテゴリーのクエリパラメータを加えて返します
     *
     * @param     string    $url    URL
     * @return    string    URL
     */
    public function add_cat_query($url) {
        if (isset($this->cat)) {
            $url = add_query_arg('cat', $this->cat, $url);
        }
        return $url;
    }
}

$DateCategoryArchives = new DateCategoryArchives();

変更点

留意点

プラグイン有効化時にwp_get_archives('cat=1')で出力したリンクの遷移先のテンプレートは、category.phpが優先されます。カテゴリー別と日付別で前者が優先されるのは、wp-includes/template-loader.phpの処理手順を見るとわかります。これをdate.phpやarchives.phpに変更したい場合は以下の方法があります。

まあそもそもカテゴリーと日付という異なる軸を同時に表示させようとしているので、若干の無理が生じてしまってます。機会があれば、ダッシュボードでどのテンプレートを利用するか設定できるようにも対応してみたいと思います。

http://deeeki.sitemix.jp/files/wordpress/date-category-archives.zip

shamyshamy 2010/10/14 23:12 はじめまして。
質問させてください。

WPにてカテゴリー別の月別アーカイブを実現するため、最初はArchives for a categoryを入れてみたのですが、うまく動作しませんでした。
(おそらくWordPressのバージョンが3.0.1のためかと)
他にいい方法がないか探していたところ、こちらの記事をみつけて早速プラグインをインストールさせていただきました。

が、Archives for a category同様、記事アーカイブがソートされず、カテゴリートップと同じ内容の記事が並んでいるといった状態でした。
やはりWordPress3.0.1の環境では、こちらのプラグインでもカテゴリー&月別アーカイブ実装というのは難しいのでしょうか...。

deeekideeeki 2010/10/15 05:39 こんにちは。
ローカルですがこちらの動作確認環境(WP3.01)では動作しています。
<?php wp_get_archives('cat=1') ?>で出力されるURLを対象にしています。
テーマや他のプラグインの影響もあるかもしれませんが、
具体的にどのURLのときに動作しないのか教えていただければ、対応できると思います。

shamyshamy 2010/10/15 14:04 早速のご返答ありがとうございます!
パーマリンク設定を「/%category%/%postname%.html」に変更しており、
「http://example.com/2010/01/?cat=5」
といったURLで動作しません。

テーマはオリジナルで作っており、カテゴリー毎にcategory-slug.phpを作成しています。
テンプレート内はheader.phpとfooter.phpを読み込ませ、sidebar.phpは使用していません。

...とここまで書きながら、ふとテンプレート内のループ前に記述していたquery_posts記述を外してみたら、なんと見事に表示されました!

こちらの素人ミスで大変失礼しました。
おかげさまで何日も頭を悩ませていたところを救っていただき、
大変感謝しております!
安心して使えるこのプラグインをこれからも愛用させていただきます。

deeekideeeki 2010/10/15 19:50 確かにテーマの中でquery_posts()していたら、取得記事が上書きされると思います。
解決されたようでよかったです。
野良プラグインで不具合もあるかもしれませんが、使っていただいて幸いです!

yumiyumi 2010/10/25 13:42 はじめまして。wpのバージョンを3.0.1にしたところ、「Archives for a category」が動かなくなってしまい、たいへん困っていたところでした。deeeki様のプラグインで無事解決しました!本当にありがとうございました。

deeekideeeki 2010/10/25 23:06 なんとなく公開してみたつもりだったのですが、
問題なく使っていただいているのを確認できると、安心します。
コメントどうもありがとうございます!

koukou 2011/01/10 13:50 wp_get_archives('type=yearly')
としたところ「年」の文字が表示されず「2011」のみ表示されるのですがどのようにすればいいでしょうか?

deeekideeeki 2011/01/10 15:28 プラグイン関係なくWordPressの仕様で「年」は出力されないですね。
本体のカスタマイズなのでバージョンアップ時に注意が必要ですが、
wp-includes/general-template.phpの946行目辺りを以下のようにすれば表示できます。
$text = sprintf('%d年', $arcresult->year);

koukou 2011/01/10 19:52 プラグインは関係なかったのですね^^;
失礼いたしました。
変更したところ思うように表示されました!

ちなみになんですがコアファイルを変更した場合、バージョンアップした際に全て上書きされてしまいますよね?

変更する箇所だけを記載したphpを別途作成しそれを読み込めばバージョンアップしても変更が維持されるというようなうまく回避する何かいい方法ってないものでしょうか?

deeekideeeki 2011/01/11 00:34 wp_get_archives()はフックがあまり用意されていないので難しいですね。
・'get_archives_link'フィルターフックで年のみの場合を判定して処理
・テーマでwp_get_archives()を使わず直接PHPで現在からブログ開始年でループして出力
のどちらかの方法ならバージョンアップ上書きは回避できると思います。

sachisachi 2011/05/20 19:01 はじめまして。
冒頭のshamyさんと同じく動作しないのですが、バージョンが3.1だからでしょうか?
■パーマリンク /%category%/%postname%/
■表示されるURL http://example.com/2010/01/?cat=5
テーマはオリジナルでcategory.php内にheader.php、footer.php、sidebar.phpとカテゴリー別のテーマ example.phpを条件分岐で読み込んでいます。テーマ内ではquery_postsではなくget_postsを使用しています。なにぶんワードプレス歴は極めて浅いものでして(汗)どうかご助言お願いいたします!

deeekideeeki 2011/05/21 08:48 WordPressにもともとある記事取得処理を上書きしているため、テーマ内でquery_posts()やget_posts()を利用して独自に記事取得していると、うまく動きません。
カテゴリー別テーマの分岐はquery_post()などを利用しなくてもis_category()のみでできるはずですので、試してみてくださいー。

sachi sachi 2011/05/23 11:01 ありがとうございます!
is_category()で解決いたしました(涙)

popslampopslam 2011/11/16 20:35 3.2.1でも動くのでしょうか?
<?php wp_get_archives('type=postbypost&limit=12&cat=1'); ?>
の用にsidebarに書いているのですがダメでしょうか?
PHP素人です。

popslampopslam 2011/11/17 05:24 うごいたうごいた。すごいすごい。

よしよし 2011/12/01 10:48 Archives for a categoryの代替品を探してたどり着きました。助かりました。

http://www.webopixel.net/wordpress/236.html
のようなrewrite ruleを作成していたら、このURLを生成できるようになるともっといいですね。

dandandandan 2012/04/10 12:42 うおおおお。最初動かなかったのですが、postをis_category()にかえたらいきました!!感謝感謝!

abeabe 2013/02/13 18:34 3.2.1で動きました。Archives for a categoryでパーマリンクに ?cat=1 がうまく設定されず、困ってたどり着きました。助かりました。

aki_star02aki_star02 2013/07/12 11:30 先日Twitterでお願いしたaki_star02です。
質問をさせてください。


このプラグインを使ったのですが、アーカイブされた月別リンクをクリックすると、以下のエラーが出ました。

Fatal error: Uncaught exception 'Exception' with message 'DateTime::__construct(): ' in C:\Users\username\Dropbox\xampp\site\sitedate\wpsite\wp-content\plugins\hansel-gretel\HAG_Crumb.php:404 Stack trace: #0 C:\Users\username\Dropbox\xampp\site\sitedate\wpsite\wp-content\plugins\hansel-gretel\HAG_Crumb.php(404): DateTime->__construct('2013???4???11??...') #1 C:\Users\username\Dropbox\xampp\site\sitedate\wpsite\wp-content\plugins\hansel-gretel\HAG_Crumb.php(243): HAG_Crumb::get_date_archive_crumbs(Array) #2 C:\Users\username\Dropbox\xampp\site\sitedate\wpsite\wp-content\plugins\hansel-gretel\hansel-gretel.php(117): HAG_Crumb::get_crumbs(Array) #3 C:\Users\username\Dropbox\xampp\site\sitedate\wpsite\wp-content\plugins\hansel-gretel\hansel-gretel.php(146): HAG_Breadcrumbs::display(NULL) #4 C:\Users\username\Dropbox\xampp\site\sitedate\wpsite\wp-content\themes\themename\archive_content.php(13): HAG_Breadcrumbs() #5 C:\Users\username\Dropbox\xampp\site\sitedate\wpsite\wp-includes\template.php(409): require('C:\Users\akinag...') #6 C:\Users\username C:\Users\username\Dropbox\xampp\site\sitedate\wpsite\wp-content\plugins\hansel-gretel\HAG_Crumb.php on line 404

※パスなどは変えていますが、エラー分はこのままです。


調べてみたのですが、タイムスタンプがおかしいなどのサイトが出てきて、php.infoを直せば直るなどの情報があり、
事情があり触れないので困っています。

もし原因をご存じでしたら教えていただけないでしょうか?

よろしくお願いいたします。

deeekideeeki 2013/07/12 19:20 Hansel & Gretel というプラグインの問題と思われます。一度 Hansel & Gretel を無効にして試していただくといいかもしれません。それでエラーが起きなければ、Hansel & Gretel を修正するか、同時に利用するのをあきらめる必要があると思います。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証