web-dev-qa-db-fra.com

Obtenir Suivant/Précédent 3 messages par rapport au message actuel

J'ai 7 posts, comme ceci:

1
2
3
4 - c'est le poste actuel
5
6
7

Comme indiqué, le numéro quatre est la publication en cours d’affichage. J'ai besoin de créer une requête qui me permettra d'afficher les 3 articles précédents (par date de publication) et les trois articles suivants. Cela peut être fait avec deux requêtes distinctes.

J'ai pu afficher le post précédent ou suivant immédiatement, mais pas ceux plus bas/haut.

Des idées?

6
Pippin

Cela peut être fait en une seule requête, bien que je ne puisse pas parler spécifiquement de la performance de cette requête (je n'ai pas dépensé beaucoup d'argent avec les requêtes de l'Union - je n'avais jamais eu besoin, jusqu'à maintenant) ..

Tout d'abord, une fonction permettant de sélectionner deux ensembles de résultats, mais en utilisant l'union pour les renvoyer sous la forme d'un ensemble de résultats unique.

function get_post_siblings( $limit = 3, $date = '' ) {
    global $wpdb, $post;

    if( empty( $date ) )
        $date = $post->post_date;

    //$date = '2009-06-20 12:00:00'; // test data

    $limit = absint( $limit );
    if( !$limit )
        return;

    $p = $wpdb->get_results( "
    (
        SELECT 
            p1.post_title, 
            p1.post_date,
            p1.ID
        FROM 
            $wpdb->posts p1 
        WHERE 
            p1.post_date < '$date' AND 
            p1.post_type = 'post' AND 
            p1.post_status = 'publish' 
        ORDER by 
            p1.post_date DESC
        LIMIT 
            $limit
    )
    UNION 
    (
        SELECT 
            p2.post_title, 
            p2.post_date,
            p2.ID 
        FROM 
            $wpdb->posts p2 
        WHERE 
            p2.post_date > '$date' AND 
            p2.post_type = 'post' AND 
            p2.post_status = 'publish' 
        ORDER by
            p2.post_date ASC
        LIMIT 
            $limit
    ) 
    ORDER by post_date ASC
    " );
    $i = 0;
    $adjacents = array();
    for( $c = count($p); $i < $c; $i++ )
        if( $i < $limit )
            $adjacents['prev'][] = $p[$i];
        else
            $adjacents['next'][] = $p[$i];

    return $adjacents;
}

Il y a une date de test, vous pouvez l'ignorer en toute sécurité ou ajouter votre propre valeur pour le test.

Voici un exemple de code que vous pouvez utiliser dans votre boucle single.php pour répertorier les résultats. Notez qu’il s’agit d’un exemple générique et que la fonction peut nécessiter la sélection de données supplémentaires J'ai indiqué que je ne savais pas exactement ce que vous vouliez. Par conséquent, voici un exemple et un exemple que vous pouvez utiliser pour tester les résultats.

<?php 
$siblings = get_post_siblings( 3 ); // This is the same as doing the call below(which is just for illustration)
//$siblings = get_post_siblings( 3, $post->post_date );

$prev = $siblings['prev'];

foreach( $prev as $p )
    echo get_the_time( 'd m Y', $p ) . ': ' . apply_filters( 'the_title', $p->post_title ) . '<br />';

$next = $siblings['next'];

foreach( $next as $p )
    echo get_the_time( 'd m Y', $p ) . ': ' . apply_filters( 'the_title', $p->post_title ) . '<br />';
?>

En attente d'un retour... :)

3
t31os

Cela peut être fait beaucoup mieux avec la propriété date_query de la classe WP_Query. Cela permettra d'obtenir les publications avant la date de publication de la publication en cours.

// WP_Query arguments
$args = array (
    'post_type'              => 'post',
    'post_status'            => 'publish',
     'date_query'    => array(
        'column'  => 'post_date',
        'before'   => get_the_date()
    ),
);

// The Query
$the_query = new WP_Query( $args );

.........

2
raison

3 x get_adjacent_post () :

global $post;
$current_post = $post; // remember the current post

for($i = 1; $i <= 3; $i++){
  $post = get_previous_post(); // this uses $post->ID
  setup_postdata($post);

  // do your stuff here       
  the_title();

}

$post = $current_post; // restore

idem pour les 3 prochains articles, changez simplement la fonction pour get_next_post () ...


Pour ce faire avec une seule requête, tout en utilisant toujours l'API WP, essayez de remplacer la valeur LIMIT par 3 dans les filtres get_previous_post_sort ET get_next_post_sort .

2
onetrickpony

Comme JanFabry le suggère dans une réponse à @onetrickpony ci-dessus, vous pouvez modifier get_adjacent_post (). C'est ce que j'ai fait. Voici la fonction. J'ai changé la signature de la fonction parce que cela me semblait plus logique.

/**
 * Retrieve multiple adjacent posts. Adapted from get_adjacent_post()
 *
 * Can either be next or previous post.
 *
 * @since 2.5.0
 *
 * @param int       $post_id    Optional. Will fall back to loop.
 * @param int       $limit      Optional. Number of posts to return.
 * @param bool          $previous       Optional. Whether to retrieve previous or next posts.
 * @param bool          $in_same_term   Optional. Whether post should be in a same taxonomy term.
 * @param array|string  $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
 * @param string        $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 * @return mixed        Array of post objects if successful. Null if global $post is not set. Empty string if no corresponding post exists.
 */
function pst_get_adjacent_posts( $post_id = null, $limit = 1, $previous = true, $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
    global $wpdb;

    if ( ( ! $post = get_post( $post_id ) ) || ! taxonomy_exists( $taxonomy ) )
        return null;

    $current_post_date = $post->post_date;

    $join = '';
    $posts_in_ex_terms_sql = '';
    if ( $in_same_term || ! empty( $excluded_terms ) ) {
        $join = " 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";

        if ( $in_same_term ) {
            if ( ! is_object_in_taxonomy( $post->post_type, $taxonomy ) )
                return '';
            $term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );
            if ( ! $term_array || is_wp_error( $term_array ) )
                return '';
            $join .= $wpdb->prepare( " AND tt.taxonomy = %s AND tt.term_id IN (" . implode( ',', array_map( 'intval', $term_array ) ) . ")", $taxonomy );
        }

        $posts_in_ex_terms_sql = $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy );
        if ( ! empty( $excluded_terms ) ) {
            if ( ! is_array( $excluded_terms ) ) {
                // back-compat, $excluded_terms used to be $excluded_terms with IDs separated by " and "
                if ( false !== strpos( $excluded_terms, ' and ' ) ) {
                    _deprecated_argument( __FUNCTION__, '3.3', sprintf( __( 'Use commas instead of %s to separate excluded terms.' ), "'and'" ) );
                    $excluded_terms = explode( ' and ', $excluded_terms );
                } else {
                    $excluded_terms = explode( ',', $excluded_terms );
                }
            }

            $excluded_terms = array_map( 'intval', $excluded_terms );

            if ( ! empty( $term_array ) ) {
                $excluded_terms = array_diff( $excluded_terms, $term_array );
                $posts_in_ex_terms_sql = '';
            }

            if ( ! empty( $excluded_terms ) ) {
                $posts_in_ex_terms_sql = $wpdb->prepare( " AND tt.taxonomy = %s AND tt.term_id NOT IN (" . implode( $excluded_terms, ',' ) . ')', $taxonomy );
            }
        }
    }

    $adjacent = $previous ? 'previous' : 'next';
    $op = $previous ? '<' : '>';
    $order = $previous ? 'DESC' : 'ASC';

    /**
     * Filter the JOIN clause in the SQL for an adjacent post query.
     *
     * The dynamic portion of the hook name, $adjacent, refers to the type
     * of adjacency, 'next' or 'previous'.
     *
     * @since 2.5.0
     *
     * @param string $join           The JOIN clause in the SQL.
     * @param bool   $in_same_term   Whether post should be in a same taxonomy term.
     * @param array  $excluded_terms Array of excluded term IDs.
     */
    $join  = apply_filters( "get_{$adjacent}_post_join", $join, $in_same_term, $excluded_terms );

    /**
     * Filter the WHERE clause in the SQL for an adjacent post query.
     *
     * The dynamic portion of the hook name, $adjacent, refers to the type
     * of adjacency, 'next' or 'previous'.
     *
     * @since 2.5.0
     *
     * @param string $where          The WHERE clause in the SQL.
     * @param bool   $in_same_term   Whether post should be in a same taxonomy term.
     * @param array  $excluded_terms Array of excluded term IDs.
     */
    $where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare( "WHERE p.post_date $op %s AND p.post_type = %s AND p.post_status = 'publish' $posts_in_ex_terms_sql", $current_post_date, $post->post_type), $in_same_term, $excluded_terms );

    /**
     * Filter the ORDER BY clause in the SQL for an adjacent post query.
     *
     * The dynamic portion of the hook name, $adjacent, refers to the type
     * of adjacency, 'next' or 'previous'.
     *
     * @since 2.5.0
     *
     * @param string $order_by The ORDER BY clause in the SQL.
     */
    $sort  = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT $limit" );

    $query = "SELECT p.ID FROM $wpdb->posts AS p $join $where $sort";
    $query_key = 'adjacent_post_' . md5( $query );
    $result = wp_cache_get( $query_key, 'counts' );
    if ( false !== $result ) {
        if ( $result )
            $result = array_map( 'get_post', $result );
        return $result;
    }

    $result = $wpdb->get_col( $query );
    if ( null === $result )
        $result = '';

    wp_cache_set( $query_key, $result, 'counts' );

    if ( $result )
        $result = array_map( 'get_post', $result );

    return $result;
}
0
djb