Фильтровать next_post_link () и previous_post_link () по метаданным?

8

У меня есть страница с двумя секциями, каждая использует другую , WP_Query()чтобы тянуть events, которые являются своим родом таможенного поста. Каждый WP_Query()запрашивает meta_keyдату события, чтобы в разделе 1 отображались только предстоящие события, eventsа в разделе 2 - прошедшие events.

В следующем eventsразделе 1 вся необходимая информация отображается на моей странице, поэтому щелкнуть их невозможно.

Прошлое eventsв Разделе 2 отображает только eventзаголовок и кликабельно. Когда пользователи нажимают на прошлое, eventони ссылаются на пользовательский single-event.phpшаблон для прошлого event.

Я хочу отобразить предыдущую / следующую навигацию в single-event.phpшаблоне, но навигация должна указывать только на прошлое events.

Я попытался с помощью next_post_link()и , previous_post_link()но они будут ссылаться на предстоящих eventsтоже, что я не хочу. Я, вероятно, могу установить новый WP_Query()на моем single-event.phpи перебрать его, чтобы получить идентификаторы Prev / Next, но повторение запроса кажется решительным шагом.

Я был бы очень признателен за понимание того, как отфильтровать предстоящие eventsссылки из моих предыдущих / следующих публикаций. Я видел этот вопрос, но я бы предпочел не использовать плагин.

CFX
источник
1
Ответ на этот вопрос подсказан в другом ответе на вопрос, который вы связали - вам нужно отфильтровать предложения join / where / sort в get_adjacent_postфункции.
Мило
Да, намекнул на это. Я бы очень хотел увидеть рабочий пример, если это возможно.
cfx
1
У меня нет времени что-то кодировать в данный момент, но хорошей отправной точкой было бы выполнение запроса через WP_Query, а затем проверка $your_query_object->request, которая покажет хороший кусок SQL, который вам понадобится для его выполнения.
Мило
Спасибо за подсказку @Milo, думаю, я понял это! См. ниже!
cfx

Ответы:

6

Мне удалось заставить это работать, используя только фильтры WordPress, благодаря подсказке @ Milo.

Просто отметьте, что они довольно специфичны для моего случая, но у вас не должно возникнуть проблем с их изменением для собственного использования. Я использую расширенные настраиваемые поля с полем выбора даты, dateа ссылки «Предыдущая / Следующая» указывают только на события с dateполями, установленными в любой день до сегодняшнего дня.

Я создал 5 фильтров:

  • 1 изменить JOIN(добавить wp_postmeta)
  • 1 изменить WHEREдля предыдущей ссылки
  • 1 изменить WHEREдля следующей ссылки
  • 1 изменить SORTдля предыдущей ссылки
  • 1 изменить SORTдля следующей ссылки

Вот то, что я придумал, похоже, что оно работает, но если кто-то обнаружит какие-либо проблемы, я буду рад обратной связи:

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');
CFX
источник
3

У меня была довольно похожая проблема, мне нужно было отсортировать и исключить несколько постов из предыдущей / следующей навигации. проблема с решением @ cfx заключалась в следующем: он не способен на ajax: is_singular()функция возвращает false, если вы загружаете содержимое через wp-ajax. так что он работал при загрузке страницы, но не работал, когда содержимое было изменено с помощью 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_clickableнабор для true.

Еще одна проблема, с которой я столкнулся: у меня было некоторое содержимое, созданное, а затем внедрившее это настраиваемое поле ... поэтому в запрос также были исключены посты, у которых даже это поле не было прикреплено к сообщению, независимо от того, является ли оно истинным или ложным. просто имейте это в виду, когда используете этот тип фильтрации. убедитесь, что у каждого сообщения есть значение, или учитывайте это в вашем синтаксисе sql.

honk31
источник