web-dev-qa-db-fra.com

Filtre next_post_link () et previous_post_link () par meta_key?

J'ai une page avec deux sections, chacune utilisant un WP_Query() différent pour extraire eventsname__, qui sont un type de publication personnalisé. Chaque WP_Query() interroge un meta_key pour la date de l'événement afin que la section 1 affiche uniquement le prochain eventset que la section 2 affiche le passé eventsname__.

Le prochain eventsde la section 1 affiche toutes les informations pertinentes sur ma page. Il est donc impossible de cliquer dessus.

Les eventspassés de la section 2 affichent uniquement le titre eventet sont cliquables. Lorsque les utilisateurs cliquent sur un eventpassé, ils sont liés à un modèle single-event.php personnalisé pour le passé eventname__.

Je souhaite afficher la navigation Précédent/Suivant dans le modèle single-event.php, mais la navigation ne doit pointer que vers le passé eventsname__.

J'ai essayé d'utiliser next_post_link() et previous_post_link(), mais ceux-ci renverront également à la liste suivante eventsname__, ce que je ne veux pas. Je peux probablement configurer une nouvelle WP_Query() sur mon single-event.php et la parcourir pour obtenir les ID Précédent/Suivant, mais répéter la requête semble être une étape radicale.

J'apprécierais vraiment un aperçu sur un moyen de filtrer les noms eventsà venir de mes liens de post précédents/suivants. J'ai vu cette question mais je préférerais ne pas utiliser de plugin.

8
cfx

J'ai réussi à faire fonctionner cela en utilisant uniquement des filtres WordPress, grâce à l'indice de @ Milo.

Notez simplement que celles-ci sont assez spécifiques à mon cas mais vous ne devriez pas avoir de problème à les modifier pour votre propre usage. J'utilise des champs personnalisés avancés avec un champ Sélecteur de date appelé liens date et Précédent/Suivant qui pointe uniquement vers les événements avec des champs date définis sur n'importe quel jour avant aujourd'hui.

J'ai créé 5 filtres:

  • 1 pour modifier JOIN (pour ajouter wp_postmeta)
  • 1 à modifier WHERE pour le lien précédent
  • 1 à modifier WHERE pour le lien suivant
  • 1 à modifier SORT pour le lien précédent
  • 1 à modifier SORT pour le lien suivant

Voici ce que j'ai trouvé, cela semble fonctionner, mais si quelqu'un découvre un problème, j'aimerais avoir des commentaires:

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

j'ai eu un problème assez similaire, nécessaire pour trier et exclure plusieurs messages de navigation précédente/suivante. Le problème avec @ cfx La solution était: sa n'est pas capable pour ajax: la fonction is_singular() renvoie false si vous chargez du contenu via wp-ajax. ainsi cela a fonctionné sur le chargement de page, mais pas, quand le contenu a été changé par ajax. global $post; m'aidait ici.

voici ma solution:

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

dans ce cas, la requête de champ costum est la suivante: exclure tous les articles pour lesquels cf not_clickable est défini sur true.

un autre problème que j’ai rencontré: j’avais du contenu créé, puis implémenté ce champ personnalisé par la suite. La requête excluait donc également les publications qui n’avaient même pas ce champ attaché à la publication, que ce soit vrai ou faux. gardez cela à l’esprit lorsque vous utilisez ce type de filtrage. assurez-vous que chaque message a une valeur ou considérez-le dans votre syntaxe SQL.

3
honk31