Отримуємо кілька сусідніх записів одним запитом
У WP є функції, які отримують по одному сусідньому запису get_next_post() . Але вони можуть отримати лише одну посаду. А що робити, коли потрібно отримати одразу кілька сусідніх (граничних, крайніх) записів, які розташовані поруч із поточним (навколо – до і після неї).
1 2 3 4 - поточний пост 5 6 7
Завдання можна вирішити двома запитами WP_Query , але ми зробимо це одним запитом!
/** * Отримує сусідні (за датою) записи. * * @param array $args { * Масив аргументів: * * @type int $limit По скільки сусідніх записів потрібно отримати. * @type bool $in_same_term Отримувати записи тільки з тих же термінів, в яких знаходиться поточний запис. * @type string $taxonomy Назва такси. Коли $in_same_term = true, потрібно знати з якою таксою працювати. * @type int/WP_Post $post Пост від якого йде відлік. Типово: поточний. * @type string $order Порядок сортування. При DESC - елемент 'prev' міститиме нові записи, а 'next' старі. При ASC навпаки... * @type bool $cache_result Чи потрібно кешувати результат в об'єктний кеш? * } * * @return array Масив виду array( 'prev'=>array(пости), 'next'=>array(пости) ) або array() якщо не вдалося отримати записи або в запиті є помилка. * * @ver 1.0 */ function get_post_adjacents( $args = array() ) { Global $wpdb; $args = (object) array_merge( array( 'limit' => 3, 'in_same_term' => false, 'taxonomy' => 'category', 'post' => $GLOBALS['post'], 'order' => 'DESC', 'cache_result' => false, ), $ args); $post = is_numeric($args->post) ? get_post($args->post) : $args->post; // in_same_term $join = $where = ''; if ( $args->in_same_term ) { $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"; $where .= $wpdb->prepare( "AND tt.taxonomy = %s", $args->taxonomy ); if ( ! is_object_in_taxonomy( $post->post_type, $args->taxonomy ) ) return array(); $term_array = wp_get_object_terms( $post->ID, $args->taxonomy, ['fields'=>'ids'] ); // Remove any exclusions from the term array to include. //$term_array = array_diff( $term_array, (array) $excluded_terms ); if ( ! $term_array || is_wp_error( $term_array ) ) return array(); $term_array = array_map( 'intval', $term_array ); $where .= " AND tt.term_id IN (" . implode( ',', $term_array ) . ")"; } $query = " ( SELECT p.* FROM $wpdb->posts p $join WHERE p.post_date > '". esc_sql($post->post_date). "' AND p.post_type = '". esc_sql($post->post_type). "' AND p.post_status = 'publish' $where ORDER BY p.post_date ASC LIMIT ". intval($args->limit) ." ) UNION ( SELECT * FROM $wpdb->posts WHERE ID = $post->ID ) UNION ( SELECT p.* FROM $wpdb->posts p $join WHERE p.post_date < '". esc_sql($post->post_date) ."' AND p.post_type = '". esc_sql($post->post_type) ."' AND p.post_status = 'publish' $where ORDER BY p.post_date DESC LIMIT ". intval($args->limit) ." ) ORDER by post_date ".( $args->order === 'DESC' ? 'DESC' : 'ASC' )." "; // пробуємо отримати кеш... if( $args->cache_result ){ $query_key = 'post_adjacents_'. md5($query); $result = wp_cache_get($query_key, 'counts'); if( false === $result ) $result = $wpdb->get_results( $query, OBJECT_K ); // кешуємо запит... if( ! $result ) $result = array(); wp_cache_set($query_key, $result, 'counts'); } else $result = $wpdb->get_results( $query, OBJECT_K ); // зберемо prev/next масиви if( $result ){ $adjacents = array( 'prev'=>[], 'next'=>[] ); $indx = 'prev'; foreach( $result as $pst ){ //unset($pst->post_content); // для дебага // поточний пост if( $pst->ID == $post->ID ){ $indx = 'next'; continue; } $adjacents[ $indx ][ $pst->ID ] = get_post( $pst ); // Створимо об'єкти WP_Post } } // дебаг //$posts_tits = wp_list_pluck($result, 'post_title'); //die(print_r($posts_tits)); return $adjacents; }
Приклад використання
$adjacents = get_post_adjacents( [ 'post' => 10253 ]); print_r ($ adjacents);
Отримаємо:
Array( [prev] => Array ( [10415] => WP_Post Object [ID] => 10415 [post_author] => 141 [post_date] => 2018-07-14 17:23:56 [post_date_gmt] => 2018-07-14 12:23:56 [post_title] => Contact Form 7 – показ полів за умовою ... [10339] => WP_Post Object [ID] => 10339 [post_author] => 141 [post_date] => 2018-06-19 00:40:03 [post_date_gmt] => 2018-06-18 19:40:03 [post_title] => Хуки на сторінці редагування запису ... [10276] => WP_Post Object [ID] => 10276 [post_author] => 141 [post_date] => 2018-06-14 23:35:17 [post_date_gmt] => 2018-06-14 18:35:17 [post_title] => Smart Custom Fields - простий плагін метаполів ... ) [next] => Array ( [10040] => WP_Post Object [ID] => 10040 [post_author] => 1 [post_date] => 2018-05-21 21:35:48 [post_date_gmt] => 2018-05-21 16:35:48 [post_title] => Webcraftic Clearfy: оптимізація, прискорення та захист WordPress ... [10097] => WP_Post Object [ID] => 10097 [post_author] => 1 [post_date] => 2018-05-21 13:13:21 [post_date_gmt] => 2018-05-21 08:13:21 [post_title] => Рейтинг найкращих месенджерів 2018 ... [10084] => WP_Post Object [ID] => 10084 [post_author] => 1 [post_date] => 2018-05-17 13:53:47 [post_date_gmt] => 2018-05-17 08:53:47 [post_title] => Як працюють повідомлення (пінги, трекбеки) у WordPress ... ) )