web-dev-qa-db-ja.com

カスタム投稿タイプの日付アーカイブ

私はこれに関して多くの質問/投稿を見ました、しかしまともな解決策をまだ見つけていません。基本的に私はwp_get_archivesがすることをやろうとしています、しかしカスタム投稿タイプのために(個人的に私はwp_get_archivesがカスタム投稿タイプをサポートしない理由はわからない!).

私が現在使っているコードは以下の通りです。

functions.php

function Cpt_getarchives_where_filter( $where , $r ) {
  $post_type = 'events';
  return str_replace( "post_type = 'post'" , "post_type = '$post_type'" , $where );
}

sidebar-events.php

add_filter( 'getarchives_where' , 'Cpt_getarchives_where_filter' , 10 , 2 );
wp_get_archives();
remove_filter('getarchives_where' , 'Cpt_getarchives_where_filter' , 10 );

このコードは、日付(2014年4月、2014年3月など)などを表示します。素晴らしいですが、リンクをクリックすると404に移動します。各日付リンクに作成されるURLは/ 2014/04 /です。/events/2014/04 /のように。

Archive-events.phpテンプレートを使用できるようにURLに「イベント」を含める方法はありますか。また、リンクが現在404を生成する理由はありますか?

助けてくれてありがとう

2
wickywills

毎月のアーカイブの場合は'month_link'、年間のアーカイブの場合は'year_link'、毎日のアーカイブの場合は'day_link'をフィルタリングすることもできます。

CPTを扱うようにwp_get_archivesを拡張し、'getarchives_where'とアーカイブリンクにフィルタを追加する関数を書くこともできます。

function wp_get_cpt_archives( $cpt = 'post', $args = array() ) {
  // if cpt is post run the core get archives
  if ( $cpt === 'post' ) return wp_get_archives($args); 
  // if cpt doesn't exists return error
  if ( ! post_type_exists($cpt) ) return new WP_Error('invalid-post-type');
  $pto = get_post_type_object($cpt);
  // if cpt doesn't have archive return error
  if ( ! $pto = get_post_type_object( $cpt ) ) return false;
  $types = array('monthly' => 'month', 'daily' => 'day', 'yearly' => 'year');
  $type = isset( $args['type'] ) ?  $args['type'] : 'monthly';
  if ( ! array_key_exists($type, $types) ) {
    // supporting only 'monthly', 'daily' and 'yearly' archives
     return FALSE;
  }
  $done_where = $done_link = FALSE;
  // filter where
  add_filter( 'getarchives_where' , function( $where ) use (&$done_where, $cpt) {
    if ( $done_where ) return $where;
    return str_replace( "post_type = 'post'" , "post_type = '{$cpt}'" , $where );
  });
  // filter link
  add_filter( "{$types[$type]}_link", function( $url ) use (&$done_link, $pto, $cpt) {
    if ( $done_link ) return $url;
     // if no pretty permalink add post_type url var
     // if ( get_option( 'permalink_structure' ) || ! $pto->rewrite ) {
     if ( ! get_option( 'permalink_structure' ) || ! $pto->rewrite ) {
       return add_query_arg( array( 'post_type' => $cpt ), $url );
     } else { // pretty permalink
       global $wp_rewrite;
       $slug = is_array( $pto->rewrite ) ? $pto->rewrite['slug'] : $cpt;
       $base = $pto->rewrite['with_front'] ? $wp_rewrite->front : $wp_rewrite->root;
       $home = untrailingslashit( home_url( $base ) );
       return str_replace( $home,  home_url( $base . $slug ), $url );
     }
  });
  // get original echo arg and then set echo to false  
  $notecho = isset($args['echo']) && empty($args['echo']);
  $args['echo'] = FALSE; 
  // get archives
  $archives = wp_get_archives($args);
  // prevent filter running again
  $done_where = $done_link = TRUE;
  // echo or return archives
  if ( $notecho ) {
    return $archives;
  } else {
    echo $archives;
  }
}

機能がどのように機能するかについての詳細はインラインコメントを読んでください。

今問題があります。 /events/2014/04/のようなURLはWordPressに認識されないので、その種類のURLを処理するreqriteルールを追加する必要があります。

繰り返しますが、そのルールを追加する関数を書くことができます。

function generate_cpt_archive_rules( $cpt ) {
  if ( empty($cpt) || ! post_type_exists($cpt) ) return;
  global $wp_rewrite;
  $pto = get_post_type_object($cpt);
  if ( ! $pto->has_archive ) return;
  $base = $pto->rewrite['with_front'] ? $wp_rewrite->front : $wp_rewrite->root;
  $base = trailingslashit( $base );
  $slug = is_array( $pto->rewrite ) ? $pto->rewrite['slug'] : $cpt;
  $year = ltrim( $base . $slug . '/([0-9]{4})/?$', '/' );
  $month = ltrim( $base . $slug . '/([0-9]{4})/([0-9]{2})/?$', '/' );
  $day = ltrim( $base . $slug . '/([0-9]{4})/([0-9]{2})/([0-9]{2})/?$', '/' );
  $index = 'index.php?post_type=' . $cpt;
  $rules[$year] =  $index . '&m=$matches[1]';
  $rules[$month] = $index . '&m=$matches[1]$matches[2]';
  $rules[$day] = $index . '&m=$matches[1]$matches[2]$matches[3]';
  $page = 2;
  foreach ( array( $year, $month, $day ) as $rule ) {
    $paged = str_replace( '/?$', '/page/([0-9]{1,})/?$', $rule);
    $rules[$paged] = $rules[$rule] . '&paged=$matches[' . $page . ']';
    $page++;
  }
  return $rules;
}

この関数はルールを生成しますが、それらを追加してフラッシュする必要もあります。

テーマ(またはプラグイン)の有効化に関するルールをフラッシュしてinitに登録することをお勧めします。そのため、次のようにします。

function register_cpt_dates_rules() {
  $cpts = array( 'events' );
  foreach ( $cpts as $cpt ) {
    foreach ( generate_cpt_archive_rules( $cpt ) as $rule => $rewrite ) {
      add_rewrite_rule( $rule, $rewrite, 'top' );
    }
  }
}
// flushing on theme switch
add_action('after_switch_theme', function() {
  register_cpt_dates_rules();
  $GLOBALS['wp_rewrite']->flush_rules();
});
// registering on init
add_action( 'init', 'register_cpt_dates_rules' );

これらの関数をfunctions.phpに追加したら(そして'after_switch_theme'を実行させるためにあなたのテーマを非アクティブ化し再度アクティブ化したら)、アーカイブを表示することができます。

wp_get_cpt_archives( 'events' );

そしてそれはイベントCPTのためのアーカイブを表示し、そしてリンクは何か/events/2014/04/になるでしょう。

年間または毎日のアーカイブにも使用できます。

wp_get_cpt_archives( 'events', array( 'type'=>'yearly' ) );
wp_get_cpt_archives( 'events', array( 'type'=>'daily' ) );

私の2つの関数を使用すると、wp_get_archivesをCPTで動作させるための非常に簡単な方法があります。

ここでallのコードにはPHP 5.3+が必要です。

4
gmazzap

私はG.Mがあなたが必要とするすべてを与えたと思います。 CPTの日付アーカイブのパーマリンク生成について ブログ記事 を書きましたが、他のpre_get_posts部分をブログに入れる時間がありませんでしたまだ投稿フォーム。

パズルには基本的に3つの部分があります。

  1. /2014/04/30/2014/などの日付文字列を読み取るための書き換え規則を生成します。
  2. WP_Queryにクエリ変数を認識させる。
  3. (私の投稿がカバーしている)サイドバーウィジェット用のページ付け/アーカイブリンクを作成する。
0
Eric Holmes