web-dev-qa-db-ja.com

ランダムなカスタム投稿タイプの投稿をコンテンツ内に表示する

私はfunctions.php(以下のすべてのコード)の中に、任意の与えられたsingle.php投稿にx量の段落の後に広告を追加する関数があります。広告投稿のTitle、Image、およびURLフィールドを持つadvertisingというcustom-post-typeがあります。どのsingle.php投稿でも、広告を表示するチェックボックス(true/false)と、作者が画像広告を挿入する前にスキップする段落数を選択するための数値フィールドがあります。

更新コード: 以下のコードは動作しますが、ランダムな投稿をすることができません。それは他のものに回転することなく絶対的な最新の投稿を引っ張り続けます。

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

編集: 解決しよう! orderorderbyに変更し、上記のコードは機能します。

2

すでに指摘したように、ランダムな順序付けと検索は実行するのが非常に高価な操作なので、その問題をどのようにソートするのかを見てみましょう。

あなたはあなたのカスタム投稿タイプから1つの投稿しか必要としないので、私たちは希望の投稿を取得するためにget_post()に渡すことができるランダムIDを1つだけ必要とします。データベースからランダムに投稿を取得するのではなく、すべてのカスタム投稿タイプ( または少なくともすべての投稿ID )をクエリして一時的なものに保存し、そのオプションからランダムなIDを選択します。

いくつかのコードを見てみましょう:( これは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;
}       

これまでに行ったこと、すべてのカスタム投稿タイプ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()関数からランダムな投稿IDを取得し、それをget_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;
}
2
Pieter Goosen

まず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>';
2
Sumit

ランダムオフセットを使用することは、生成されたSQLクエリでRand()による順序付けよりも速い代替方法です。

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は投稿数によって異なります。

これはそうではないかもしれないことに注意してください 素晴らしい 非常に多数の行のために、しかし興味深い ベンチマーク シート Josh Hartman もあります。

Pieter Goosenも彼の 答え に興味深いアプローチを持っています、それはあなたにRand()による順序付けよりもはるかに良い選択肢を与えるでしょう。

2
birgire