web-dev-qa-db-ja.com

Meta_keyでnext_post_link()とprevious_post_link()をフィルタリングしますか?

私は2つのセクションがあるページを持っています。それぞれが独自の投稿タイプであるeventsを引き込むために異なるWP_Query()を使用します。それぞれのWP_Query()はイベントの日付についてmeta_keyを問い合わせるので、セクション1は次のeventsのみを表示し、セクション2は過去のeventsを表示します。

セクション1の次のeventsは私のページにすべての関連情報を表示するので、それらをクリックすることは不可能です。

セクション2の過去のeventseventのタイトルのみを表示し、クリック可能です。ユーザーが過去のeventをクリックすると、過去のeventのカスタムsingle-event.phpテンプレートにリンクします。

single-event.phpテンプレートにPrevious/Nextナビゲーションを表示したいのですが、ナビゲーションは過去のeventsのみを指すようにしてください。

私はnext_post_link()previous_post_link()を使ってみましたが、これらは今後のeventsにもリンクするでしょう。おそらくsingle-event.phpに新しいWP_Query()を設定し、それをループしてPrev/Next IDを取得することができますが、クエリを繰り返すのは劇的なステップのようです。

Previous/Nextの投稿リンクから今後のeventsを除外する方法についての洞察を本当に感謝します。私は - この質問 を見ましたが、私はプラグインを使用したくないと思います。

8
cfx

@ Miloのヒントのおかげで、私はWordPressフィルタ以外は何も使わずにこれをうまく動かすことができた。

これらは私の場合にかなり特有のものであることにだけ注意してください、しかしあなたはあなた自身の使用のためにそれらを修正する問題を持つべきではありません。 dateという日付選択フィールドと高度なカスタムフィールドを使用しています。前/次のリンクはdateフィールドが今日の前日に設定されたイベントのみを指しています。

私は5つのフィルタを作成しました:

  • JOINを変更する場合は1(wp_postmetaを追加する場合)
  • 前のリンクのWHEREを変更するには1
  • 次のリンクのWHEREを変更するには1
  • 前のリンクのSORTを変更するには1
  • 次のリンクのSORTを変更するには1

これは私が思いついたものです、それはうまくいっているようですが、誰かが何か問題を見つけた場合私はフィードバックが大好きだ:

function get_adjacent_past_events_join($join) {
  if(is_singular('event')) {
    global $wpdb;
    $new_join = $join."INNER JOIN $wpdb->postmeta AS m ON p.ID = m.post_id ";
    return $new_join;
  }
  return $join;
}
add_filter('get_previous_post_join', 'get_adjacent_past_events_join');
add_filter('get_next_post_join', 'get_adjacent_past_events_join');

function get_prev_past_events_where($where) {
  if(is_singular('event')) {
    global $wpdb, $post;
    $id = $post->ID;
    $current_event_date = get_field('date', $id);
    $today = date('Ymd');
    $new_where = "WHERE p.post_type = 'event' AND p.post_status = 'publish' AND (m.meta_key = 'date' AND (m.meta_key = 'date' AND CAST(m.meta_value AS CHAR) < '$today')) AND (m.meta_key = 'date' AND (m.meta_key = 'date' AND CAST(m.meta_value AS CHAR) < '$current_event_date'))";
    return $new_where;
  }
  return $where;
}
add_filter('get_previous_post_where', 'get_prev_past_events_where');

function get_next_past_events_where($where) {
  if(is_singular('event')) {
    global $wpdb, $post;
    $id = $post->ID;
    $current_event_date = get_field('date', $id);
    $today = date('Ymd');
    $new_where = "WHERE p.post_type = 'event' AND p.post_status = 'publish' AND (m.meta_key = 'date' AND (m.meta_key = 'date' AND CAST(m.meta_value AS CHAR) < '$today')) AND (m.meta_key = 'date' AND (m.meta_key = 'date' AND CAST(m.meta_value AS CHAR) > '$current_event_date'))";
    return $new_where;
  }
  return $where;
}
add_filter('get_next_post_where', 'get_next_past_events_where');

function get_prev_past_events_sort($sort) {
  if(is_singular('event')) {
    global $wpdb;
    $new_sort = " GROUP BY p.ID ORDER BY m.meta_value+0 DESC";
    return $new_sort;
  }
  return $sort;
}
add_filter('get_previous_post_sort', 'get_prev_past_events_sort');

function get_next_past_events_sort($sort) {
  if(is_singular('event')) {
    global $wpdb;
    $new_sort = " GROUP BY p.ID ORDER BY m.meta_value+0 ASC";
    return $new_sort;
  }
  return $sort;
}
add_filter('get_next_post_sort', 'get_next_past_events_sort');
6
cfx

私はprev/nextナビゲーションからいくつかの投稿をソートしたり除外したりするのに必要な、かなり似たような問題を抱えていました。 @ cfxのソリューションの問題は、ajaxに対応していないことです。もしwp-ajaxを介してコンテンツをロードした場合、is_singular()関数はfalseを返します。そのため、ページの読み込みには効果がありましたが、コンテンツがajaxによって変更されたときには失敗しました。 global $post;が私を助けてくれました。

これが私の解決策です:

/**
  * WP: join postmeta to our sql query, so we can filter for custom fields
  *
  * @param $join
  * @return string
  */
function jnz_adjacent_work_join( $join ) {
  global $post;
  if ( get_post_type( $post ) == 'work' ) {
    global $wpdb;
    return $join . "INNER JOIN $wpdb->postmeta AS m ON p.ID = m.post_id ";
  }
  return $join;
}
add_filter('get_previous_post_join', 'jnz_adjacent_work_join');
add_filter('get_next_post_join', 'jnz_adjacent_work_join');



/**
 * WP: Change order of post for prev / next navigation
  * exclude posts with custom field "not_clickable" set to true
  *
  * @param $where
  * @param $operator
  * @return string|void
  */
 function jnz_adjacent_work_where( $where, $operator ) {
   global $post;
   if ( get_post_type( $post ) == 'work' ) :
     global $wpdb;
     $where = $wpdb->prepare("WHERE p.post_title {$operator} '%s' AND p.post_type = 'work' AND p.post_status = 'publish' AND (m.meta_key = 'not_clickable' AND (m.meta_key = 'not_clickable' AND m.meta_value != 1))", $post->post_title );
   endif;

   return $where;
 }

 $gt = '<';
 $lt = '>';
 add_filter( 'get_next_post_where', function( $where ) use ( $lt ) {
   return jnz_adjacent_work_where( $where, $lt );
 });
 add_filter( 'get_previous_post_where', function( $where ) use ( $gt ) {
   return jnz_adjacent_work_where( $where, $gt );
 });

この場合、costumフィールドのクエリは、cf not_clickabletrueに設定されているすべての投稿を除外します。

私が遭遇した別の問題:私はいくつかのコンテンツを作成し、その後そのカスタムフィールドを実装しました。この種のフィルタリングを使用する場合は、この点に留意してください。すべての投稿に値があることを確認するか、SQL構文でこれを考慮してください。

3
honk31