Next_post_link () und previous_post_link () nach meta_key filtern?

8

Ich habe eine Seite mit zwei Abschnitten, von denen jeder einen anderen verwendet WP_Query() zum Einziehen verwendet events, bei dem es sich um einen benutzerdefinierten Beitragstyp handelt. Bei jeder WP_Query()Abfrage wird a meta_keynach dem Ereignisdatum abgefragt, sodass in Abschnitt 1 nur bevorstehende eventsund in Abschnitt 2 vergangene Ereignisse angezeigt werden events.

In eventsAbschnitt 1 werden alle relevanten Informationen auf meiner Seite angezeigt, sodass ein Klicken nicht möglich ist.

Die Vergangenheit events in Abschnitt 2 zeigt nur den eventTitel an und kann angeklickt werden. Wenn Benutzer auf eine Vergangenheit klicken event, verlinken sie auf eine benutzerdefinierte single-event.phpVorlage für die Vergangenheit event.

Ich möchte die vorherige / nächste Navigation in der single-event.phpVorlage anzeigen , aber die Navigation sollte nur auf die Vergangenheit zeigen events.

Ich habe es versucht next_post_link()und previous_post_link()aber diese werden auf kommende verlinkenevents , was ich nicht will. Ich kann wahrscheinlich ein neues WP_Query()auf meinem single-event.phpeinrichten und es durchlaufen, um die Prev / Next-IDs zu erhalten, aber das Wiederholen der Abfrage scheint ein drastischer Schritt zu sein.

Ich würde mich sehr über einen Einblick in einen Weg freuen, wie eventsich aus meinen Links zu vorherigen / nächsten Beiträgen herausfiltern kann . Ich habe diese Frage gesehen , würde aber lieber kein Plugin verwenden.

cfx
quelle
1
Die Antwort darauf ist in der anderen Antwort auf die von Ihnen verknüpfte Frage angedeutet. Sie müssen die Join / Where / Sort-Klauseln in der get_adjacent_postFunktion filtern .
Milo
Ja, es wird angedeutet. Ich würde wirklich gerne ein funktionierendes Beispiel sehen, wenn möglich.
cfx
1
Ich habe im Moment keine Zeit, etwas zu codieren, aber ein guter Ausgangspunkt wäre, eine Abfrage über durchzuführen WP_Queryund dann zu überprüfen $your_query_object->request, um einen guten Teil der SQL zu erhalten, die Sie zum Abrufen benötigen.
Milo
Danke für den Hinweis @Milo, denke ich habe es herausgefunden! Siehe unten!
cfx

Antworten:

6

Dank des Hinweises von @ Milo gelang es mir, dies nur mit WordPress-Filtern zum Laufen zu bringen.

Beachten Sie nur, dass diese für meinen Fall ziemlich spezifisch sind, aber Sie sollten kein Problem damit haben, sie für Ihren eigenen Gebrauch zu ändern. Ich verwende erweiterte benutzerdefinierte Felder mit einem Datumsauswahlfeld namens dateund Prev / Next-Links verweisen nur auf Ereignisse mitdate Feldern, die auf einen Tag vor dem heutigen Tag festgelegt wurden.

Ich habe 5 Filter erstellt:

  • 1 zu ändern JOIN(hinzuzufügen wp_postmeta)
  • 1 zum Ändern WHEREfür den vorherigen Link
  • 1 zum Ändern WHEREfür den nächsten Link
  • 1 zum Ändern SORTfür den vorherigen Link
  • 1 zum Ändern SORTfür den nächsten Link

Folgendes habe ich mir ausgedacht: Es scheint zu funktionieren, aber wenn jemand Probleme entdeckt, würde ich mich über Feedback freuen:

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
quelle
3

Ich hatte ein ziemlich ähnliches Problem, musste mehrere Beiträge sortieren und von der vorherigen / nächsten Navigation ausschließen. Das Problem mit der Lösung von @ cfx war: Es ist nicht für Ajax geeignet: Die is_singular()Funktion gibt false zurück, wenn Sie Inhalte über wp-ajax laden. So funktionierte es beim Laden der Seite, aber nicht, als der Inhalt von Ajax geändert wurde.global $post;half mir hier raus.

Hier ist meine Lösung:

/**
  * 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 );
 });

In diesem Fall lautet die Kostümfeldabfrage: Alle Beiträge ausschließen, auf die cf not_clickablegesetzt ist true.

Ein weiteres Problem, auf das ich gestoßen bin: Ich habe einige Inhalte erstellt und anschließend dieses benutzerdefinierte Feld implementiert. Daher hat die Abfrage auch die Beiträge ausgeschlossen, an die dieses Feld nicht einmal angehängt war, egal ob wahr oder falsch. Denken Sie daran, wenn Sie diese Art der Filterung verwenden. Stellen Sie sicher, dass jeder Beitrag einen Wert hat, oder berücksichtigen Sie diesen in Ihrer SQL-Syntax.

honk31
quelle