web-dev-qa-db-fra.com

Obtenir un message aléatoire de type message personnalisé à afficher dans le contenu

J'ai une fonction, dans functions.php (tout le code ci-dessous), qui ajoute une publication après x quantité de paragraphes à un message single.php donné. J'ai un type de message personnalisé appelé advertising qui comporte un champ Titre, Image et URL pour le message publicitaire. Dans toute publication single.php, j'ai une case à cocher pour afficher la publicité (vrai/faux) et un champ numérique permettant à l'auteur de choisir le nombre de paragraphes à ignorer avant l'insertion de la publicité illustrée.

MISE À JOUR CODE: code ci-dessous fonctionne, mais je ne peux pas obtenir un message aléatoire. Il continue de tirer le dernier message absolu sans se tourner vers les autres.

// 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: RESOLU! order a été remplacé par orderby et le code ci-dessus fonctionne.

3
Alexander Graham

Comme nous l'avons déjà indiqué, l'ordre et la recherche aléatoires sont des opérations assez coûteuses à exécuter. Voyons donc comment nous allons régler ce problème.

Étant donné que vous n'avez besoin que d'un message de votre type de message personnalisé, nous n'avons besoin que d'un seul ID aléatoire que nous pouvons transmettre à get_post() afin d'obtenir le message souhaité. Au lieu d'obtenir la publication de manière aléatoire de la base de données, nous interrogerons tous les types de publication personnalisés ( ou au moins tous les ID de publication ), l'enregistrerons dans un transitoire, puis nous pourrons simplement sélectionner un identifiant aléatoire à partir de cette option.

Regardons un code: ( Ceci va dans 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;
}       

Ce que nous avons fait, nous avons maintenant enregistré tous les identifiants de type de publication personnalisés dans un transitoire. Cela augmentera considérablement les performances. Le transitoire est défini sur 30 jours, nous devons donc vider et recréer le transitoire dès que nous publions un nouveau type de publication personnalisé.

Permet d'utiliser le hook d'action transition_post_status: ( Ceci va dans 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 );

Tout ce qui nous reste à faire est d’obtenir un ID de publication aléatoire de notre fonction get_random_id() et de le transmettre à get_post() pour obtenir l’objet de publication.

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

De cette façon, vous économisez beaucoup sur les ressources et cela est beaucoup plus rapide que de simplement laisser SQL choisir une publication aléatoire dans la base de données.

À titre d’exemple, le filtre de votre annonceur peut ressembler à ce qui suit:

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

Commencez par recevoir le message publicitaire aléatoire par get_posts

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

Maintenant, récupère les champs personnalisés de ce message aléatoire

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

Construisez votre annonce HTML et insérez où vous voulez!

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

L'utilisation d'un décalage aléatoire peut constituer une alternative plus rapide que la commande par Rand() dans la requête SQL générée:

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'
        ] 
    );
}

où nous utilisons offset pour définir la partie SQL LIMIT x, 1, où x dépend du nombre de publications.

Notez que cela n’est peut-être pas le cas great pour un très grand nombre de lignes, mais il existe également un intéressant benchmark feuille par Josh Hartman .

Pieter Goosen a également une approche intéressante dans son answer , qui devrait vous offrir une bien meilleure alternative que de commander par Rand().

2
birgire