I have two Custom Post Types and would like to display one of them sorted (by title) and the other one at random places in the same query.
So CPT A (sorted) en CPT B (random):
A1 A2 A3 B2 A4 A5 B5 A6 A7 A8 A9 B1 ...
or
A1 B1 A2 A3 B5 A4 A5 A6 A7 A8 A9 B7 ...
or
B4 A1 A2 A3 A4 B3 A5 A6 A7 A8 B1 A9 ...
I tried merging the two CPT but that didn't work as expected.
$projectposts = get_posts(array(
'posts_per_page' => -1,
'post_type' => 'project',
'order' => 'ASC'
));
//second query
$storieposts = get_posts(array(
'posts_per_page' => -1,
'post_type' => 'storie',
'order' => 'rand'
));
$mergedposts = array_merge( $projectposts, $storieposts ); //combined querie
@kero:
I have this ↓ and it's almost working... It looks like this creates some empty entries in the array. (I'm 100% certain that there are no empty titles before merging.)
The query results in A3 A2 A4 A6 B2 (empty) (empty) (empty) A1 (empty) (empty) B1 B3 ...
$projectposts = get_posts([
'posts_per_page' => -1,
'post_type' => 'project',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'featured',
'value' => '"homepagina"',
'compare' => 'LIKE'
)
)
]);
$storieposts = get_posts([
'posts_per_page' => -1,
'post_type' => 'story',
'order' => 'ASC',// not rand!
'meta_query' => array(
array(
'key' => 'featured',
'value' => '"homepagina"',
'compare' => 'LIKE'
)
)
]);
function array_random_merge(array $a, array $b): array {
while (count($b) > 0) {
shuffle($b);
// get one entry of $b
$item = array_shift($b);
// find random position inside $a
$pos = mt_rand(0, count($a) - 1);
// insert $item into $a
array_splice($a, $pos, 0, $item);
}
return $a;
}
$mergedposts = array_random_merge($projectposts, $storieposts);
if( $mergedposts ) {
foreach( $mergedposts as $post ) {
echo '<h3>';
echo the_title();
echo '</h3>';
}
}
wp_reset_postdata();
I have two Custom Post Types and would like to display one of them sorted (by title) and the other one at random places in the same query.
So CPT A (sorted) en CPT B (random):
A1 A2 A3 B2 A4 A5 B5 A6 A7 A8 A9 B1 ...
or
A1 B1 A2 A3 B5 A4 A5 A6 A7 A8 A9 B7 ...
or
B4 A1 A2 A3 A4 B3 A5 A6 A7 A8 B1 A9 ...
I tried merging the two CPT but that didn't work as expected.
$projectposts = get_posts(array(
'posts_per_page' => -1,
'post_type' => 'project',
'order' => 'ASC'
));
//second query
$storieposts = get_posts(array(
'posts_per_page' => -1,
'post_type' => 'storie',
'order' => 'rand'
));
$mergedposts = array_merge( $projectposts, $storieposts ); //combined querie
@kero:
I have this ↓ and it's almost working... It looks like this creates some empty entries in the array. (I'm 100% certain that there are no empty titles before merging.)
The query results in A3 A2 A4 A6 B2 (empty) (empty) (empty) A1 (empty) (empty) B1 B3 ...
$projectposts = get_posts([
'posts_per_page' => -1,
'post_type' => 'project',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'featured',
'value' => '"homepagina"',
'compare' => 'LIKE'
)
)
]);
$storieposts = get_posts([
'posts_per_page' => -1,
'post_type' => 'story',
'order' => 'ASC',// not rand!
'meta_query' => array(
array(
'key' => 'featured',
'value' => '"homepagina"',
'compare' => 'LIKE'
)
)
]);
function array_random_merge(array $a, array $b): array {
while (count($b) > 0) {
shuffle($b);
// get one entry of $b
$item = array_shift($b);
// find random position inside $a
$pos = mt_rand(0, count($a) - 1);
// insert $item into $a
array_splice($a, $pos, 0, $item);
}
return $a;
}
$mergedposts = array_random_merge($projectposts, $storieposts);
if( $mergedposts ) {
foreach( $mergedposts as $post ) {
echo '<h3>';
echo the_title();
echo '</h3>';
}
}
wp_reset_postdata();
Share
Improve this question
edited Jan 13, 2021 at 19:36
zuperuser
asked Jan 13, 2021 at 11:43
zuperuserzuperuser
111 silver badge3 bronze badges
6
|
Show 1 more comment
2 Answers
Reset to default 1Try to get two different arrays of posts and loop through array A. Before get post data of A element get random element from array B.
For example:
$array_a = ['post_id_a1', 'post_id_a2', 'post_id_a3'];
$array_b = ['post_id_b1', 'post_id_b2', 'post_id_b3'];
foreach ( $array_a as $a_post_id ) {
$is_b_should_displayed = mt_rand( 0, 1 );
if ( $is_b_should_displayed && $b_length = count( $array_b ) ){
$b_to_show = mt_rand( 0, $b_length - 1 );
// show random B post
unset( $array_b[ $b_to_show ] );
$array_b = array_values( $array_b ); // to reorder array after unset
}
// show A post
}
Or in same way create array C, and then loop through C to display posts. There is no warranty all B will displayed, so, if you need it, you could loop through B (if at least 1 element exist) after main A loop
Small note: rand
using for key orderby
not to order according to wp docs.
Hope it helps
I would probably do it like this:
$projects = get_posts([
'posts_per_page' => -1,
'post_type' => 'project',
'order' => 'ASC',
]);
$stories = get_posts([
'posts_per_page' => -1,
'post_type' => 'storie',
'order' => 'ASC',// not rand!
]);
function array_random_merge(array $a, array $b): array {
while (count($b) > 0) {
shuffle($b);
// get one entry of $b
$item = array_shift($b);
// find random position inside $a
$pos = mt_rand(0, count($a) - 1);
// insert $item into $a
array_splice($a, $pos, 0, $item);
}
return $a;
}
$merged = array_random_merge($projects, $stories);
The main idea here is the following:
- remove one
$item
from$b
- insert that at a random position in
$a
- repeat 1 & 2 until
$b
is empty.
Per Tom's comment I removed rand
order in the query and simple shuffle()
the array.
rand
order is extremely heavy/slow/expensive, always do the random part in PHP where possible, as a random order can involve a full table copy into a temporary table that gets shuffled randomly, queried, then destroyed. It would be significantly faster to fetch all stories and randomly sort them after theget_posts
call – Tom J Nowell ♦ Commented Jan 13, 2021 at 12:28B1 B2 B3 A1 A2 ..
/A1 A2 B1 B2 A3 A4 B3 ..
? If not, what are your other additional rules for the distribution of B? – kero Commented Jan 13, 2021 at 14:38