Получать случайный пост-пост-пост для отображения в контенте

У меня есть функция, в functions.php (весь код ниже), которая добавляет рекламу после x количества абзацев к любому заданному сообщению single.php . У меня есть таргетинг на пост-тип, называемый advertising который имеет поле Title, Image и URL для рекламного сообщения. В любом сообщении single.php меня есть флажок, чтобы показывать объявление (true / false) и поле number для автора, чтобы выбрать, сколько абзацев пропустить, прежде чем вставлять рекламную рекламу.

ОБНОВЛЕННЫЙ КОД: код ниже работает, однако я не могу получить случайную запись. Он продолжает вытягивать абсолютный последний пост, не вращаясь с другими.

 // http parser function addhttp($url) { if (!preg_match("~^(?:f|ht)tps?://~i", $url)) { $url = "http://" . $url; } return $url; } // filter content with ad add_filter( 'the_content', 'prefix_insert_post_ads' ); function prefix_insert_post_ads( $content ) { // checkbox to show ad, default true if ( get_field('show_advertisement') ) { if ( is_single() && ! is_admin() ) { // get post-type $random_ad = get_posts(array( 'numberposts' => 1, 'post_type' => 'advertising', 'order' => 'rand', 'posts_per_page'=>'1' )); // get post-type fields $random_ad = array_shift($random_ad); $link = addhttp( get_field('advertisement_link', $random_ad->ID)); $image = get_field('upload_advertisement', $random_ad->ID); // get html $ad_code = '<a href="'.$link.'" target="_blank"><img src="'.$image.'" /></a>'; // show ad after # paragraphs $show_after = get_field('advertisement_show_after'); // return appended $content return prefix_insert_after_paragraph( $ad_code, $show_after, $content ); } else { // do nothing } } else { return $content; } } // insert ad into post function prefix_insert_after_paragraph( $insertion, $paragraph_id, $content ) { $closing_p = '</p>'; $paragraphs = explode( $closing_p, $content ); foreach ($paragraphs as $index => $paragraph) { if ( trim( $paragraph ) ) { $paragraphs[$index] .= $closing_p; } if ( $paragraph_id == $index + 1 ) { $paragraphs[$index] .= $insertion; } } return implode( '', $paragraphs ); } 

EDIT: РЕШАЕМ! Изменен order и приведенный выше код работает.

Как уже отмечалось, случайный порядок и поиск – довольно дорогостоящие операции для запуска, поэтому давайте посмотрим, как мы собираемся сортировать эту проблему.

Поскольку вам нужен только один пост из вашего настраиваемого типа сообщений, нам нужен только один случайный идентификатор, который мы можем передать get_post() , чтобы получить нужную запись. Вместо того, чтобы случайно получать сообщение из db, мы будем запрашивать все пользовательские типы сообщений ( или, по крайней мере, все идентификаторы сообщений ), сохраняя это в переходный период, а затем мы можем просто выбрать случайный идентификатор из этой опции.

Давайте посмотрим на некоторый код: ( Это идет в functions.php )

 function get_random_id( $post_type = '' ) { $q = []; // Make sure we have a post type set, check if it exists and sanitize $post_type = filter_var( $post_type, FILTER_SANITIZE_STRING ); if ( !$post_type ) return $q; if ( !post_type_exists( $post_type ) ) return $q; // The post type exist and is valid, lets continue $transient_name = 'rand_ids_' . md5( $post_type ); // Get the transient, if we have one already if ( false === ( $q = get_transient ( $transient_name ) ) ) { $args = [ 'post_type' => $post_type, 'posts_per_page' => -1, 'fields' => 'ids', // get only post ID's // Add any additional arguments ]; $q = get_posts( $args ); // Set the transient set_transient( $transient_name, $q, 30*DAY_IN_SECONDS ); } // endif get_transient return $q; } 

Что мы сделали, мы сохранили все пользовательские идентификаторы типа post в переходный период. Это увеличит производительность на огромную сумму. Переходный период установлен на 30 дней, поэтому нам нужно очистить и воссоздать переходный процесс, как только мы опубликуем новое сообщение типа post post.

Давайте используем hook_post_status: ( Это входит в функции.php )

 add_action( 'transition_post_status', function ( $new_status, $old_status, $post ) { // Make sure we only target our specific post type if ( 'advertising' !== $post->post_type ) return; global $wpdb; // Delete the transients $wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient%_rand_ids_%')" ); $wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient_timeout%_rand_ids_%')" ); // Lets rebuild the transient get_random_id( $post->post_type ); }, 10, 3 ); 

Все, что нам осталось, это получить случайный идентификатор сообщения из нашей функции get_random_id() и передать это get_post() чтобы получить объект post

 // Get the array of post ID's $post_type_posts = get_random_id( 'advertising' ); // Make sure we have posts if ( $post_type_posts ) { // Get the post object of the id first in line shuffle( $post_type_posts ); $single_post = get_post( $post_type_posts[0] ); // Display the post content } 

Таким образом, вы много экономите на ресурсах и намного быстрее, чем просто позволить SQL выбрать случайную запись из базы данных

Так же, как пример, фильтр рекламы вашего рекламодателя может выглядеть примерно так:

 add_filter( 'the_content', 'prefix_insert_post_ads' ); function prefix_insert_post_ads( $content ) { // checkbox to show ad, default true if ( get_field('show_advertisement') ) { if ( is_single() && ! is_admin() ) { // Get the array of post ID's $post_type_posts = get_random_id( 'advertising' ); // Make sure we have posts if ( $post_type_posts ) { // Get the post object of the id first in line shuffle( $post_type_posts ); $random_ad = get_post( $post_type_posts[0] ); // Display the post content $link = addhttp( get_field('advertisement_link', $random_ad->ID)); $image = get_field('upload_advertisement', $random_ad->ID); // get html $ad_code = '<a href="'.$link.'" target="_blank"><img src="'.$image.'" /></a>'; // show ad after # paragraphs $show_after = get_field('advertisement_show_after'); // return appended $content return prefix_insert_after_paragraph( $ad_code, $show_after, $content ); } } } return $content; } 

Использование случайного смещения может быть более быстрой альтернативой, чем упорядочение по RAND() в сгенерированном SQL-запросе:

 if( $count = wp_count_posts( 'advertising' )->publish ) { $random_ad = get_posts( [ 'post_status' => 'publish', 'offset' => rand( 0, $count - 1 ), 'posts_per_page' => 1, 'post_type' => 'advertising' ] ); } 

где мы используем offset для установки LIMIT x, 1 SQL-части, где x зависит от количества сообщений.

Обратите внимание, что это может быть не так хорошо для очень большого количества строк, но есть и интересный контрольный лист Джоша Хартмана .

Pieter Goosen также имеет интересный подход в своем ответе , который должен дать вам гораздо лучшую альтернативу, чем заказать RAND() .

Сначала получите случайный рекламный пост get_posts

 $random_ad = get_posts(array( 'numberposts' => 1, 'post_type' => 'advertising', 'orderby' => 'rand' )); 

Теперь получите пользовательские поля из этой случайной записи

 if (!empty($random_ad)) { $random_ad = array_shift($random_ad); $link = addhttp( get_field('advertisement_link', $random_ad->ID)); $image = get_field('upload_advertisement', $random_ad->ID); } 

Создайте свое объявление HTML и вставьте туда, где хотите!

 $ad_code = '<a href="'.$link.'" target="_blank"><img src="'.$image.'" /></a>';