J'ai une boucle dans une boucle. J'ai compris comment afficher tout ou X nombre de messages personnalisés après le nombre Y de messages normaux. J'ai également compris comment afficher 1 message personnalisé après chaque Y message normal. Comment puis-je afficher X messages personnalisés après CHAQUE Y nombre de messages normaux.
En termes simples. Comment afficher 2 posts de livre (type de post personnalisé) après 4 envois de blog? Comment peut-on extraire plus d'un message à la fois de la boucle?
c’est la logique des x messages personnalisés après les y messages normaux. Comment puis-je obtenir x messages personnalisés après TOUTES les publications normales?
main query // normal query
$k=0 // setting iterator
while have posts, the post
---post markup---
if($k == 4 or $k % 4 == 0) { // whether after x number or after every x number
second query // using WP_Query
while second query has posts, the posts
---custom post type markup // I NEED TO SHOW MORE THAN ONE HERE IF IT IS AFTER EVERY X blogposts
endwhile; //second query ends
}
$k++;
endwhile // main query
Voici une idée:
PPP
name__Y
name__X
name__Y
à injecter à chaque fois: y
name__X
à afficher avant d'injecter les messages Y
name__: x
name__Nous utiliserons:
PPP(Y) = y * floor( ( PPP(X) -1 ) / x )
où PPP(X)
, x
et y
sont positifs.
Configuration 1:
PPP(X)=1, x=3, y=2, PPP(Y) = 2 * floor( (1-1)/3 ) = 2 * 0 = 0
Loop: X
Configuration 2:
PPP(X)=3, x=3, y=2, PPP(Y) = 2 * floor( (3-1)/3 ) = 2 * 0 = 0
Loop: XXX
Configuration 3:
PPP(X)=4, x=3, y=2, PPP(Y) = 2 * floor( (4-1)/3 ) = 2 * 1 = 2
Loop: XXX YY X
Configuration 4:
PPP(X)=11, x=3, y=2, PPP(Y) = 2 * floor( (11-1)/3 ) = 2 * 3 = 6
Loop: XXX YY XXX YY XXX YY XX
Configuration 5:
PPP(X)=12, x=3, y=2, PPP(Y) = 2 * floor( (12-1)/3 ) = 2 * 3 = 6
Loop: XXX YY XXX YY XXX YY XXX
Configuration 6:
PPP(X)=13, x=3, y=2, PPP(Y) = 2 * floor( (13-1)/3 ) = 2 * 4 = 8
Loop: XXX YY XXX YY XXX YY XXX YY X
Essayons de trouver un moyen d'injecter les articles Y
dans la boucle de X
name__, sans modifier directement les fichiers de modèle.
Nous voulons nous associer à l'action loop_start
pour la requête principale du type de message X
et récupérer les articles PPP(Y)
de type Y
name__.
Ensuite, nous voulons utiliser le hook the_post
pour afficher:
get_template_part( 'content', 'y' );
Nous pouvons utiliser par exemple les propriétés current_post
et posts_per_page
de l'objet $wp_query
principal pour contrôler la logique d'injection.
Je pense qu'il est plus facile d'appeler WP_Query()
pour chaque injection, mais nous nous contentons de l'appeler seulement une fois avant la boucle principale.
Créez un fichier pièce modèle dans le répertoire de votre thème actif, par exemple content-page.php
, contenant:
<article>
<header class="entry-header">
<h2 class="entry-title"><?php the_title(); ?></h2>
</header>
<div class="entry-content">
<?php the_content(); ?>
</div>
</article>
Ensuite, vous pouvez essayer ce qui suit:
add_action( 'wp', function(){
// We want the injection only on the home page:
if( ! is_home() ) return;
// Start the injection:
$inject = new WPSE_Inject( array(
'items_before_each_inject' => 3,
'cpt_items_per_inject' => 2,
'cpt' => 'page',
'template_part' => 'content-page',
'paged' => ( $pgd = get_query_var( 'paged' ) ) ? $pgd : 1,
) );
$inject->init();
});
et le modifier à vos besoins.
La classe WPSE_Inject
est définie comme suit:
/**
* class WPSE_Inject
*
* Inject custom posts into the main loop, through hooks,
* with only a single WP_Query() call
*
* @link http://wordpress.stackexchange.com/a/141612/26350
*
* Definitions:
* Posts per page: PPP
* Custom post type: Y
* Main query post type: X
* How many Y posts to inject: y
* How many X posts to display before injecting the Y posts: x
*
* Formula:
* PPP(Y) = y * floor( ( PPP(X) -1 ) / x )
* where PPP(X), x and y are positive
*/
class WPSE_Inject
{
protected $results = NULL;
protected $query = NULL;
protected $nr = 0;
protected $inject_mode = FALSE;
protected $args = array();
public function __construct( $args = array() )
{
$defaults = array(
'items_before_each_inject' => 5,
'cpt_items_per_inject' => 1,
'cpt' => 'post',
'paged' => 1,
'template_part' => 'content-post'
);
$this->args = wp_parse_args( $args, $defaults );
}
public function init()
{
add_action( 'loop_start', array( $this, 'loop_start' ) );
add_action( 'loop_end', array( $this, 'loop_end' ) );
}
public function cpt_items_on_this_page( WP_Query $query )
{
$count = $this->args['cpt_items_per_inject'] * floor( ( $query->get( 'posts_per_page' ) -1 ) / $this->args['items_before_each_inject'] );
return ( $count > 0 ) ? $count : 1;
}
public function loop_start( WP_Query $query )
{
$this->query = $query;
if( $query->is_main_query() )
{
$args = array(
'post_type' => $this->args['cpt'],
'posts_per_page' => $this->cpt_items_on_this_page( $query ),
'paged' => $this->args['paged'],
'suppress_filters' => TRUE,
);
$this->results = new WP_Query( $args );
add_action( 'the_post', array( $this, 'the_post' ) );
}
}
public function loop_end( WP_Query $query )
{
if( $query->is_main_query() )
remove_action( 'the_post', array( $this, 'the_post' ) );
}
public function the_post()
{
if( ! $this->inject_mode
&& 0 < $this->nr
&& 0 === $this->nr % $this->args['items_before_each_inject'] )
{
$this->inject_mode = TRUE;
$this->results->rewind_posts();
$this->results->current_post = ( absint( $this->nr / $this->args['items_before_each_inject'] ) -1 ) * $this->args['cpt_items_per_inject'] - 1;
$j = 1;
if ( $this->results->have_posts() ) :
while ( $this->results->have_posts() ) :
$this->results->the_post();
get_template_part( $this->args['template_part'] );
if( $this->args['cpt_items_per_inject'] < ++$j )
break;
endwhile;
wp_reset_postdata();
endif;
$this->inject_mode = FALSE;
}
if( ! $this->inject_mode )
$this->nr++;
}
}
J'ai testé cela sur le thème par défaut, où j'ai injecté le contenu page
dans la boucle principale post
name__. La pagination semblait également fonctionner.
Cela peut être affiné davantage, mais j'espère que c'est un point de départ pour vous.