¿Pueden los enlaces Next/Prev Post ordenarse por orden de menú o por meta key?

19 nov 2012, 19:23:48
Vistas: 28.3K
Votos: 40

Tengo una serie de entradas que están ordenadas por un valor meta_key. También podrían organizarse por orden de menú, si fuera necesario.

Los enlaces de entrada siguiente/anterior (generados por next_post_link, previous_post_link, o posts_nav_link) todos navegan por cronología. Si bien entiendo este comportamiento predeterminado, no entiendo cómo cambiarlo. Descubrí que se conecta a adjacent_post_link en link-template.php, pero luego parece estar bastante codificado de forma rígida. ¿Se recomienda reescribir esto desde cero para reemplazarlo, o hay una mejor solución?

2
Comentarios

Ten en cuenta que la segunda respuesta parece dar el resultado correcto.

Thomas Thomas
11 mar 2016 14:34:10
Todas las respuestas a la pregunta 13
7
36

Entendiendo los internos

El "orden" de clasificación de las publicaciones adyacentes (siguiente/anterior) no es realmente un "orden" de clasificación. Es una consulta separada en cada solicitud/página, pero ordena la consulta por post_date - o por el padre de la publicación si tienes una publicación jerárquica como objeto mostrado actualmente.

Cuando echas un vistazo a los internos de next_post_link(), verás que básicamente es un envoltorio de API para adjacent_post_link(). Esta última función llama internamente a get_adjacent_post() con el argumento/bandera $previous establecido en bool(true|false) para obtener el enlace de la publicación siguiente o anterior.

¿Qué filtrar?

Después de profundizar en ello, verás que get_adjacent_post() Enlace fuente tiene algunos filtros interesantes para su salida (también conocido como resultado de consulta): (Nombre/Argumentos del Filtro)

  • "get_{$adjacent}_post_join"

    $join
    // Solo si `$in_same_cat`
    // o: ! empty( $excluded_categories` 
    // y luego: 
    // " INNER JOIN $wpdb->term_relationships AS tr 
    //     ON p.ID = tr.object_id 
    // INNER JOIN $wpdb->term_taxonomy tt 
    //     ON tr.term_taxonomy_id = tt.term_taxonomy_id"; 
    // y si $in_same_cat entonces AGREGA: 
    // " AND tt.taxonomy = 'category' 
    // AND tt.term_id IN (" . implode(',', $cat_array) . ")";
    $in_same_cat
    $excluded_categories
    
  • "get_{$adjacent}_post_where"

    $wpdb->prepare(
          // $op = $previous ? '<' : '>'; | $current_post_date
           "WHERE p.post_date $op %s "
          // $post->post_type
          ."AND p.post_type = %s "
          // $posts_in_ex_cats_sql = " AND tt.taxonomy = 'category' 
          // AND tt.term_id NOT IN (" . implode($excluded_categories, ',') . ')'; 
          // O cadena vacía si $in_same_cat || ! empty( $excluded_categories
          ."AND p.post_status = 'publish' $posts_in_ex_cats_sql "
        ",
        $current_post_date,
        $post->post_type
    )
    $in_same_cat
    $excluded_categories
    
  • "get_{$adjacent}_post_sort"

    "ORDER BY p.post_date $order LIMIT 1"`
    

Así que puedes hacer mucho con esto. Eso comienza con filtrar la cláusula WHERE, así como la tabla JOIN y la declaración ORDER BY.

El resultado se almacena en caché en la memoria para la solicitud actual, por lo que no agrega consultas adicionales si llamas a esa función varias veces en una sola página.

Construcción automática de consultas

Como @StephenHarris señaló en los comentarios, hay una función central que podría ser útil al construir la consulta SQL: get_meta_sql() - Ejemplos en el Codex. Básicamente, esta función solo se usa para construir la declaración SQL de metadatos que se usa en WP_Query, pero puedes usarla en este caso (u otros) también. El argumento que le pasas es una matriz, exactamente la misma que agregarías a un WP_Query.

$meta_sql = get_meta_sql(
    $meta_query,
    'post',
    $wpdb->posts,
    'ID'
);

El valor de retorno es una matriz:

$sql => (array) 'join' => array(),
        (array) 'where' => array()

Así que puedes usar $sql['join'] y $sql['where'] en tu devolución de llamada.

Dependencias a tener en cuenta

En tu caso, lo más fácil sería interceptarlo en un pequeño plugin (mu) o en el archivo functions.php de tu tema y modificarlo dependiendo de la variable $adjacent = $previous ? 'previous' : 'next'; y la variable $order = $previous ? 'DESC' : 'ASC';:

Los nombres reales de los filtros

Así que los nombres de los filtros son:

  • get_previous_post_join, get_next_post_join
  • get_previous_post_where, get_next_post_where
  • get_previous_post_sort, get_next_post_sort

Envuelto como un plugin

...y la devolución de llamada del filtro sería (por ejemplo) algo como lo siguiente:

<?php
/** Plugin Name: (#73190) Alterar el orden de clasificación de enlaces de publicaciones adyacentes */
function wpse73190_adjacent_post_sort( $orderby )
{
    return "ORDER BY p.menu_order DESC LIMIT 1";
}
add_filter( 'get_previous_post_sort', 'wpse73190_adjacent_post_sort' );
add_filter( 'get_next_post_sort', 'wpse73190_adjacent_post_sort' );
19 nov 2012 19:40:07
Comentarios

+1. Solo para información, (@magnakai) si vas a hacer algo como esto para metaqueries, echa un vistazo a get_meta_sql()

Stephen Harris Stephen Harris
19 nov 2012 20:30:12

+1 para ti @StephenHarris ! No había visto esto antes. Pregunta rápida: Según leo en el código fuente, tienes que pasar un objeto de consulta completamente calificado, ¿cómo harías esto con los filtros mencionados anteriormente? Hasta donde puedo ver, solo se pasan cadenas de consulta, ya que la consulta se ejecuta después de los filtros.

kaiser kaiser
19 nov 2012 20:58:39

no, $meta_query es simplemente el array que pasarías a WP_Query para el argumento meta_query: En este ejemplo: $meta_sql = get_meta_sql( $meta_query, 'post', $wpdb->posts, 'ID'); - esto genera las partes JOIN y WHERE de la consulta que necesitarían ser añadidas.

Stephen Harris Stephen Harris
19 nov 2012 21:41:06

@StephenHarris Momento perfecto para editar una (mi) respuesta.

kaiser kaiser
20 nov 2012 02:28:57

@StephenHarris, estoy teniendo problemas para aplicar el resultado de get_meta_sql() - ¿puedes ayudarme a conectar los puntos?

Jodi Warren Jodi Warren
20 nov 2012 13:27:27

@Magnakai es un array de $sql => (array) 'join' => array(), 'where' => array(). Así que simplemente toma $sql['join']; o $sql['where'].

kaiser kaiser
26 nov 2013 19:13:39

Esto funcionó, excepto que los enlaces están invertidos. El previous_post_link genera el enlace que debería generar next_post_link y viceversa. Intenté cambiar el orden de DESC a ASC y aún así lo hace.

Dan Dan
10 may 2019 16:53:23
Mostrar los 2 comentarios restantes
2
27

La respuesta de Kaiser es increíble y detallada, sin embargo, simplemente cambiar la cláusula ORDER BY no es suficiente a menos que tu menu_order coincida con tu orden cronológico.

No puedo atribuirme el crédito por esto, pero encontré el siguiente código en este gist:

<?php
/**
 * Personalizar el orden de los enlaces de posts adyacentes
 */
function wpse73190_gist_adjacent_post_where($sql) {
  if ( !is_main_query() || !is_singular() )
    return $sql;

  $the_post = get_post( get_the_ID() );
  $patterns = array();
  $patterns[] = '/post_date/';
  $patterns[] = '/\'[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\'/';
  $replacements = array();
  $replacements[] = 'menu_order';
  $replacements[] = $the_post->menu_order;
  return preg_replace( $patterns, $replacements, $sql );
}
add_filter( 'get_next_post_where', 'wpse73190_gist_adjacent_post_where' );
add_filter( 'get_previous_post_where', 'wpse73190_gist_adjacent_post_where' );

function wpse73190_gist_adjacent_post_sort($sql) {
  if ( !is_main_query() || !is_singular() )
    return $sql;

  $pattern = '/post_date/';
  $replacement = 'menu_order';
  return preg_replace( $pattern, $replacement, $sql );
}
add_filter( 'get_next_post_sort', 'wpse73190_gist_adjacent_post_sort' );
add_filter( 'get_previous_post_sort', 'wpse73190_gist_adjacent_post_sort' );

He modificado los nombres de las funciones para WP.SE.

Si solo cambias la cláusula ORDER BY, la consulta sigue buscando posts mayores o menores que la fecha actual del post. Si tus posts no están en orden cronológico, no obtendrás el post correcto.

Esto cambia la cláusula WHERE para buscar posts donde el menu_order sea mayor o menor que el menu_order del post actual, además de modificar la cláusula ORDER BY.

La cláusula ORDER BY tampoco debería estar codificada para usar DESC, ya que necesitará cambiar según si estás obteniendo el enlace del siguiente o del anterior post.

16 abr 2013 06:18:47
Comentarios

Una nota: La cláusula WHERE busca el formato 'YYYY-mm-dd HH:mm:ss'. Si no se cumple ese formato, no funcionará. Como el valor no lo establece la base de datos, sino la aplicación, tendrás que verificar primero ese formato al construir la expresión regular.

kaiser kaiser
6 abr 2014 15:11:15

Si deseas ordenar por post_title, puedes reemplazar todas las instancias de menu_order en el código anterior y debería funcionar bien. Pero ten cuidado con el segundo elemento del array $replacements - tuve que envolverlo entre comillas simples para que funcione, es decir: $replacements[] = '\'' . $the_post->post_title . '\'';

Ben Stevens Ben Stevens
1 jul 2021 22:26:28
5

Intenté engancharlo sin éxito. Puede que sea solo un problema de mi configuración, pero para aquellos que no pueden hacer que el hook funcione, aquí está la solución más simple:

<?php
    $all_posts = new WP_Query(array(
        'orderby' => 'menu_order',
        'order' => 'ASC',
        'posts_per_page' => -1
    ));

    foreach($all_posts->posts as $key => $value) {
        if($value->ID == $post->ID){
            $nextID = $all_posts->posts[$key + 1]->ID;
            $prevID = $all_posts->posts[$key - 1]->ID;
            break;
        }
    }
?>
<?php if($prevID): ?>
    <span class="prev">
        <a href="<?= get_the_permalink($prevID) ?>" rel="prev"><?= get_the_title($prevID) ?></a>
    </span>
<?php endif; ?>
<?php if($nextID): ?>
    <span class="next">
        <a href="<?= get_the_permalink($nextID) ?>" rel="next"><?= get_the_title($nextID) ?></a>
    </span>
<?php endif; ?>
26 oct 2017 13:38:52
Comentarios

después de unas horas intentando que get_previous_post_where, get_previous_post_join y get_previous_post_sort funcionen correctamente con tipos de posts personalizados y ordenamientos complejos que incluyen meta keys, me rendí y usé esto. ¡Gracias!

squarecandy squarecandy
13 jul 2018 01:52:16

Lo mismo aquí, no solo quería ordenar por Menu Order, sino también buscar posts con un meta_key y meta_value específicos, por lo que este fue el mejor método. El único cambio que hice fue envolverlo en una función.

MrCarrot MrCarrot
10 feb 2019 10:35:30

este código es susceptible a errores fuera de rango

eballeste eballeste
2 abr 2020 04:35:51

@eballeste, si te refieres a obtener la primera publicación cuando estás en la última y la última cuando estás en la primera, mira mi respuesta a continuación

Eli Jayson Eli Jayson
3 abr 2020 22:10:50

sí, lo vi después y voté a favor, gracias

eballeste eballeste
9 abr 2020 02:38:44
0
/**
 * Modifica la consulta SQL para ordenar posts adyacentes por menu_order en lugar de post_date
 * 
 * @param string $sql La consulta SQL original
 * @return string La consulta SQL modificada
 */
function wpse73190_gist_adjacent_post_sort( $sql ) {
    $pattern = '/post_date/';
    $replacement = 'menu_order';

    return preg_replace( $pattern, $replacement, $sql );
}

// Aplicar el filtro tanto para el post siguiente como para el anterior
add_filter( 'get_next_post_sort', 'wpse73190_gist_adjacent_post_sort' );
add_filter( 'get_previous_post_sort', 'wpse73190_gist_adjacent_post_sort' );
20 jun 2013 08:00:36
0

Por si sirve de ayuda, aquí está cómo puedes ordenar por menu_order para un tipo de entrada personalizado específico:

/**
 * Personalizar el orden de las entradas adyacentes
 */
add_filter('get_next_post_sort', function($order) {
    if (is_singular('my_custom_post_type')) {
        return 'ORDER BY p.menu_order ASC LIMIT 1';
    }

    return $order;
}, 10);

add_filter('get_previous_post_sort', function($order) {
    if (is_singular('my_custom_post_type')) {
        return 'ORDER BY p.menu_order DESC LIMIT 1';
    }

    return $order;
}, 10);

add_filter('get_next_post_where', function() {
    if (is_singular('my_custom_post_type')) {
        global $post, $wpdb;
        return $wpdb->prepare("WHERE p.menu_order > %s AND p.post_type = %s AND p.post_status = 'publish'", $post->menu_order, $post->post_type);
    }
}, 10);

add_filter('get_previous_post_where', function() {
    if (is_singular('my_custom_post_type')) {
        global $post, $wpdb;
        return $wpdb->prepare("WHERE p.menu_order < %s AND p.post_type = %s AND p.post_status = 'publish'", $post->menu_order, $post->post_type);
    }
}, 10);

¡Espero que esto le sea útil a alguien más!

4 ago 2021 21:00:58
0

Basado en la respuesta de @Szabolcs Páll, he creado esta clase de utilidad con métodos auxiliares para poder obtener publicaciones de un tipo por orden de menú y también obtener la publicación siguiente y anterior por orden de menú. Además, he añadido condiciones para verificar si la publicación actual es la primera o la última, para así obtener la última o primera publicación respectivamente.

Por ejemplo:

// $currentPost es la primera por orden de menú
getPreviousPostByMenuOrder($postType, $$currentPost->ID)
// devuelve => última publicación por orden de menú

// $currentPost es la última por orden de menú
getPreviousPostByMenuOrder($postType, $$currentPost->ID)
// devuelve => primera publicación por orden de menú

La clase completa:

class PostMenuOrderUtils {

    public static function getPostsByMenuOrder($postType){
        $args =[
            'post_type' => $postType,
            'orderby' => 'menu_order',
            'order' => 'ASC',
            'posts_per_page' => -1
        ];

        $posts = get_posts($args);

        return $posts;
    }

    public static function getNextPostByMenuOrder($postType, $postID){
        $posts = self::getPostsByMenuOrder($postType);

        $nextPost = null;

        foreach($posts as $key => $value) {
            if($value->ID == $postID){
                $nextPost = $posts[$key] !== end($posts) ? $posts[$key + 1] : $posts[0];

                break;
            }
        }

        return $nextPost;
    }

    public static function getPreviousPostByMenuOrder($postType, $postID){
        $posts = self::getPostsByMenuOrder($postType);


        $prevPost = null;

        foreach($posts as $key => $value) {
            if($value->ID == $postID){
                $prevPost = $key !== 0 ? $posts[$key - 1] : end($posts);
                break;
            }
        }

        return $prevPost;
    }

}
16 may 2019 23:04:20
1

Basado en la respuesta de @Szabolcs Páll y el post de bbloomer sobre agregar botones de anterior/siguiente en la página de producto único de WooCommerce, creé este código.

Ordena todos los productos por clave meta y agrega botones de anterior/siguiente arriba + abajo del producto.

(¡La clave meta puede ser también un campo ACF!)

/**
 * @snippet       Agregar botones anterior/siguiente ordenados por clave meta o campo ACF @ WooCommerce Página de Producto Único
 * @testedwith    WooCommerce 4.8.0
 * @source        Elron : https://wordpress.stackexchange.com/a/365334/98773
 * @thanks        bbloomer : https://businessbloomer.com/?p=20567
 * @thanks        Szabolcs Páll : https://wordpress.stackexchange.com/a/284045/98773
 */

add_action('woocommerce_before_single_product', 'elron_prev_next_product');

// y si también los quieres al final...
add_action('woocommerce_after_single_product', 'elron_prev_next_product');

function elron_prev_next_product()
{
   global $post;

   echo '<div class="prev-next-buttons">';

   $all_posts = new WP_Query(
      array(
         'post_type' => 'product',
         'meta_key' => 'the_meta_key_or_acf_field', // <-- CAMBIA ESTO
         'orderby' => 'meta_value',
         'order' => 'DESC',
         'posts_per_page' => -1
      )
   );

   foreach ($all_posts->posts as $key => $value) {
      if ($value->ID == $post->ID) {
         $nextID = $all_posts->posts[$key + 1]->ID;
         $prevID = $all_posts->posts[$key - 1]->ID;
         break;
      }
   }

   if ($prevID) : ?>
      <a href="<?= get_the_permalink($prevID) ?>" rel="prev" class="prev" title="<?= get_the_title($prevID) ?>"><?= esc_attr__('Producto anterior') ?></a>
   <?php endif; ?>
   <?php if ($nextID) : ?>
      <a href="<?= get_the_permalink($nextID) ?>" rel="next" class="next" title="<?= get_the_title($nextID) ?>"><?= esc_attr__('Producto siguiente') ?></a>
   <?php endif; ?>
<?php

   echo '</div>';
}

Si quieres el archivo scss adicional que usé: _prev-next-buttons.scss

.prev-next-buttons {
    background: $lightpurple;
    padding: 2em;
    text-align: center;

    a {
        opacity: 0.7;
        border-radius: 0.5em;
        border: $white 1px solid;
        color: $white;
        display: inline-block;
        padding: 0.5em 0.8em;
        text-decoration: none;
        margin: 0 0.1em;
        &:hover, &:focus {
            opacity: 1;
        }
    }

    .prev {
        &:before {
            content: "  ";
        }
    }
    .next {
        &:after {
            content: "  ";
        }
    }
}

.rtl {
    .prev-next-buttons {
        .prev {
            &:before {
                content: "  ";
            }
        }
        .next {
            &:after {
                content: "  ";
            }
        }
    }
}

28 abr 2020 21:51:17
Comentarios

Gracias por la valiosa información. Lo he usado con mi tipo de publicación personalizado que también tiene un campo de fecha personalizado. Funcionó perfectamente en WordPress 5.9.3. También puedo confirmar que funcionó con los tipos de publicaciones personalizados y campos que fueron creados usando plugins de terceros como ACF.

Mycodingproject Mycodingproject
10 may 2022 14:44:00
2

Ninguna de las respuestas listadas aquí o en internet en general que pude encontrar al momento de escribir esto parecía ofrecer una solución razonablemente simple/elegante para presentar los enlaces de Siguiente/Anterior Post ordenados por meta key. Esto funciona bien para mí y es fácil de adaptar. ¡Disfrútalo!

add_filter( 'get_previous_post_where', function( $where ) {
    return get_adjacent_post_where( $where, false) ;
});
add_filter( 'get_next_post_where', function ( $where ) {
    return get_adjacent_post_where( $where, true );
}); 

function get_adjacent_post_where( $where, $is_next ) {  

    global $post;

    /* Ingresa tu tipo de post -> */
    $post_type = "_my_post_type_";

    if ($post_type == $post->post_type){

        global $wpdb;

        $show_private = current_user_can( 'read_private_pages', $post->ID );
        /* Ingresa el nombre de tu meta key personalizada -> */
        $meta_key = '_my_meta_key_name_'; 
        $meta_value = get_post_meta($post->ID,$meta_key,true);
        $operand = $is_next?">":"<";
        $direction = $is_next?"ASC":"DESC";

        $sub_query = "(SELECT m.post_id FROM `" . $wpdb->postmeta . "` AS m JOIN `" . $wpdb->posts . "` as p1 ON m.post_id = p1.ID "
        . "WHERE m.meta_key = '$meta_key' AND m.meta_value $operand '$meta_value' "
        . "AND (p1.post_status = 'publish'" . ($show_private?" OR p1.post_status = 'private') ":") ")
        . "ORDER BY m.meta_value $direction LIMIT 1)";
         
        /* La subconsulta anidada soluciona limitaciones actuales de mysql/mariadb */
        $where = "WHERE p.post_type = '$post_type'  AND p.ID IN (SELECT * FROM $sub_query as sq)";  
    }

    return $where;

}
28 ene 2024 20:24:54
Comentarios

Tienes algunas referencias a tablas con prefijos en tu código, por ejemplo kc_wppostmeta y kc_wpposts. La mejor práctica es usar el objeto global $wpdb para especificar estas tablas, por ejemplo $wpdb->posts en lugar de kc_wpposts.

También creo que vale la pena mencionar que esto asume que estás obteniendo contenido publicado públicamente o de forma privada en tu subconsulta. Hay una sección completa de condiciones que manejan esto en el código principal: https://github.com/WordPress/wordpress-develop/blob/8338c630284124bbe79dc871822d6767e3b45f0b/src/wp-includes/link-template.php#L1893

MikeNGarrett MikeNGarrett
2 feb 2024 22:17:57

Gracias @MikeNGarrett. Se han realizado las modificaciones. Por favor, avísame si me he equivocado en algo.

Collie Collie
5 feb 2024 02:55:03
0

Este pequeño plugin me resulta muy útil: http://wordpress.org/plugins/wp-query-powered-adjacent-post-link/

WP_Query Powered Adjacent Post Link es un plugin para desarrolladores. Añade la función wpqpapl(); a WordPress, la cual puede devolver información sobre el post anterior y siguiente al actual. Acepta argumentos para ser usados en la clase WP_Query.

26 nov 2013 20:17:59
0

Esto funcionó para mí:

add_filter( 'get_previous_post_where', 'so16495117_mod_adjacent_bis' );
add_filter( 'get_next_post_where', 'so16495117_mod_adjacent_bis' );
function so16495117_mod_adjacent_bis( $where ) {
    global $wpdb;
    return $where . " AND p.ID NOT IN ( SELECT post_id FROM $wpdb->postmeta WHERE ($wpdb->postmeta.post_id = p.ID ) AND $wpdb->postmeta.meta_key = 'archive' AND $wpdb->postmeta.meta_value = 1 )";
}

Tomado de: https://stackoverflow.com/questions/16495117/how-to-skip-certain-links-on-adjacent-posts-in-wordpress

12 mar 2015 16:22:08
0

Yo también tuve problemas con esto. Mágicamente logré que funcionara de esta manera:

Y no tuve que escribir ni una sola línea de código yo mismo :)

4 feb 2020 18:03:26
0

Edite el código de Szabolcs Páll mencionado anteriormente para ordenar por una meta_key personalizada y dentro de una categoría específica, pero también para intentar agregar condicionales para el primer y último post.

En el primer y último post no mostraba el enlace siguiente/anterior correcto con el código original, solo mostraba un enlace para el ID de post actual en el que me encontraba.

Esto funcionó para mí como se muestra a continuación, pero no estoy seguro si hay posibles problemas con ello. (No soy el programador más avanzado)

<?php
$all_posts = new WP_Query(array(
    'taxonomy' => 'category',
    'category_name' => 'projects',
    'meta_key' => 'grid_number_projects',
    'orderby' => 'meta_value',
    'order' => 'ASC',
    'posts_per_page' => -1
));
foreach($all_posts->posts as $key => $value) {
    if($value->ID == $post->ID){
        $nextID = isset($all_posts->posts[$key + 1]) ? $all_posts->posts[$key + 1]->ID : null;
        $prevID = isset($all_posts->posts[$key - 1]) ? $all_posts->posts[$key - 1]->ID : null;
        break;
    }
}

?>

<div class="project-nav-prev">
    <?php if($prevID): ?>
        <a href="<?= get_the_permalink($prevID) ?>" rel="prev"><span class="arrow">←</span> PROYECTO ANTERIOR </br><?= get_the_title($prevID) ?></a>
    <?php endif; ?>
</div>
<div class="project-nav-next">
    <?php if($nextID): ?>
        <a href="<?= get_the_permalink($nextID) ?>" rel="next">SIGUIENTE PROYECTO <span class="arrow">→</span> </br><?= get_the_title($nextID) ?></a>
    <?php endif; ?>
</div>
23 mar 2023 14:18:59
4
-2

He encontrado una forma mucho más fácil de lograr una navegación entre publicaciones basada en meta-claves, sin necesidad de modificar functions.php.

Mi ejemplo: Tienes un products.php y quieres navegar entre productos. El producto anterior es el siguiente más barato, el siguiente producto es el siguiente más caro.

Aquí está mi solución para single.php:

<div class="post_navigation">

<?php

// Preparar el loop
$args = array(
'post_type' => 'products',
'post_status' => 'publish',
'meta_key' => 'price',
'orderby' => 'meta_value_num',
'order' => 'ASC',
'posts_per_page' => -1
);
query_posts($args);

// Inicializar array donde se almacenarán los IDs de TODAS las publicaciones de productos
$posts = array();

// ... y ahora iniciemos el loop
while ( have_posts() ) : the_post();
$posts[] += $post->ID;
endwhile;

// Resetear Query
wp_reset_query();

// Identificar la posición del producto actual dentro del array $posts 
$current = array_search(get_the_ID(), $posts);

// Identificar ID del producto anterior
$prevID = $posts[$current-1];

// Identificar ID del siguiente producto
$nextID = $posts[$current+1];

// Enlace "producto anterior"
if (!empty($prevID)) { ?>
<a href="/?p=<?php echo $prevID; ?>">producto anterior</a>
<?php }
// Enlace "siguiente producto"
if (!empty($nextID)) { ?>
<a href="/?p=<?php echo $nextID; ?>">siguiente producto</a>

<?php } ?>
21 may 2014 11:25:46
Comentarios

-10 por esta respuesta. ¿Cómo puede ser una mejor solución si estás usando query_posts cuando el codex establece que no debería usarse?

Pieter Goosen Pieter Goosen
21 may 2014 11:31:30

pero funciona. ¿entonces la alternativa es WP_Query o qué?

Kent Miller Kent Miller
21 may 2014 12:22:49

Sí, se debe usar WP_Query como en las respuestas anteriores.

Pieter Goosen Pieter Goosen
21 may 2014 12:27:09

@KentMiller, hay un diagrama informativo en la página del codex, y también puede encontrar esta pregunta bastante útil. Vale la pena familiarizarse con estas convenciones.

Jodi Warren Jodi Warren
21 may 2014 13:56:19