获取随机自定义帖子类型的帖子以在内容中显示

时间:2016-02-24 作者:Alexander Graham

我有一个函数,在functions.php (以下所有代码),在x 任何给定的段落数量single.php 邮递我有一个自定义的帖子类型,叫做advertising 具有用于广告帖子的标题、图像和URL字段。在任何single.php post I有一个复选框来显示广告(真/假)和一个数字字段,供作者选择插入图像广告之前要跳过多少段落。

UPDATED CODE: 下面的代码可以工作,但我无法获得随机帖子。它不停地拖动最新的帖子,而不转到其他帖子。

// 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: 已解决!已更改orderorderby 上述代码也可以工作。

3 个回复
最合适的回答,由SO网友:Pieter Goosen 整理而成

正如前面所指出的,随机排序和搜索是非常昂贵的操作,所以让我们看看如何对该问题进行排序。

因为您只需要自定义帖子类型中的一个帖子,所以我们只需要一个随机ID,可以传递给get_post() 为了得到想要的职位。我们不会从db中随机获取帖子,而是查询所有自定义帖子类型(或至少所有帖子ID),将其保存到瞬态中,然后我们可以从该选项中选择一个随机ID。

让我们看看一些代码:(这将进入函数。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类型ID保存到瞬态中。这将极大地提高性能。过渡期设置为30天,因此我们需要在发布新的自定义帖子类型帖子后立即刷新并重新创建过渡期。

让我们使用transition_post_status 动作挂钩:(这将进入functions.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从DB中随机选择一篇文章要快得多

例如,您的广告注入器过滤器可以如下所示

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;
}

SO网友:Sumit

首先通过以下方式获得随机广告帖子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>\';

SO网友:birgire

使用随机偏移量可能比按排序更快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 取决于职位数量。

请注意,情况可能并非如此great 对于非常多的行,但是还有一个有趣的benchmark 工作表编制人Josh Hartman.

Pieter Goosen在他的answer, 这应该会给您提供比订购更好的选择RAND().

相关推荐