2 custom wp_query using the same rand with 'orderby' => 'rand'? - php

On my home page I'm showing 9 post, I have a load more button (with ajax) who calls 9 other posts and so on. Currently I'm ordering by 'date' but I would like to order by random. The problem is that my first wp_query orderby rand shows 9 random post, and when I load more post my second wp_query orderby random too can shows the same post from the first 9 post.
How can I randomize 2 wp_query with the same random ? Or is there another way to do this ?
As it is already suggest by a community member, I tried to store visibles Id in an array and used post__not_in like :
$query = new WP_QUERY(array(
'post_type' => 'my_posts',
'posts_per_page' => 9,
'orderby' => 'rand',
'post__not_in' => $postNoIn,
'paged' => $paged
));
But this didn't solve my problem.
The $paged variable is the current page number for my posts. I have 32 posts and I'm getting them 9 by 9, so there is 4 pages. When I use the second wp_query displays above, I get 9 random post minus the possible 9 first posts, so I can have less than 9 post and the query stopped when the last page in reached. I will have about 28 posts and not 32 cause the query stopped at page 4 and not until all posts are displayed.
Thanks in advance for your answers !
I've finally succeeded !
Here is my answer
I change my first query to get all post order by "rand", like :
$args = array(
'post_type' => 'my_posts',
'posts_per_page' => -1,
'orderby' => 'rand'
);
Then in my loop I display the 9 first posts, after 9 posts I get the ID of all the others posts
<?php
$index = 0;
$idsInt = array();
while ($the_query->have_posts()):
$the_query->the_post();
if ($index < 9) :
get_template_part('part-template/content', get_post_format());
$index++;
else :
array_push($idsInt, get_the_ID());
endif;
endwhile;
After that I prepare my data to be use with ajax, for this I convert my list of int element into a string list
$index = 0;
$idsString = array();
foreach ($idsInt as $id) {
if ($index == 0) {
$idsString .= " \"" . $id . "\"";
} else {
$idsString .= ", \"" . $id . "\"";
}
$index++;
}
Here is my "Load More" button, I put in "data-id" my list of ID
<div class="text-center">
<a id="btn-load-more" data-id='[<?php echo $idsString ?>]'
class="home-load-more"
data-page="1"
data-url="<?php home_url(); ?>/wp-admin/admin-ajax.php" >
<span class="text"><?php _e('Load More') ?></span>
</a>
</div>
In my script.js, my ajax function looks like :
$(document).on('click', '.home-load-more', function () {
let that = $(this);
let page = that.data('page');
let newPage = page + 1;
let ajaxurl = that.data('url');
let ids = that.data('id');
$.ajax({
url: ajaxurl,
type: 'post',
data: {
page: page,
action: 'home_load_more',
foo : ids
},
error: function (response) {
console.log(response);
},
success: function (response) {
if (!(response === "")) {
that.data('page', newPage);
$('.my_row').append(response);
}
}
});
});
My $_POST['page'] contains a number of page that increment on every Load More call, I'll explain why I'm using it later, and my $_POST['foo'] contains my list of ID create in my first query loop.
Now my php functions !
( explications of my code in the php comments ! )
function home_load_more()
{
$ids = ($_POST['foo']);
$paged = $_POST["page"];
$postIn = array();
// I want to display only 9 posts on each calls
for ($i = 0; $i < 9; $i++) {
/* Here is my strange calcul to get ids
- from 0 to 8 on the first call
- from 9 to 17 on the second call
- from 18 to 26 on the third call
and so on...
That is why I use the $paged, to get
a value that is increment by one on every calls. */
// Break if they are no more ids in the list
if ($ids[($paged - 1) * 9 + $i] == null) {
break;
}
// $postIn contains 9 posts IDs
array_push($postIn, $ids[($paged - 1) * 9 + $i]);
}
$query = new WP_QUERY(array(
'post_type' => 'my_posts',
'orderby' => 'post__in', // here I give my list of 9 ids
'post__in' => $postIn
));
if ($postIn[0] == null) {
// Load More button won't display any posts
wp_reset_postdata();
} else {
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
get_template_part('part-template/content', get_post_format());
}
}
wp_reset_postdata();
}
die();
}
That's it ! I think there is a best way to do this but I still want to show you my code. Hope this can help somebody, and if you have comment, questions, or ideas, don't hesitate to tell me in the comment section !

Just store already visible ids somewhere in array, when requesting load more, send that array, then include it to $args
$args = array (
...
'post__not_in' => array( 1, 2, 3),
...
);

Related

Get a list of child pages via a function in wordpress

I am trying to get a list of child pages to display on the parent page via wordpress. The best way I can describe what I am trying to do is if you are on the about page (/about) but you want to go to the meet the team page (/about/meet-the-team) when you are on the about page it should then display a link to the meet the team page.
I have this code at the moment
function getPagesHierarchy() {
$pagesQuery = new WP_Query(array(
'post_type' => 'page',
'posts_per_page' => -1,
'post_parent' => 0,
'order' => 'ASC',
'post_status' => 'publish'
)) ;
if ($pagesQuery->have_posts()) {
while($pagesQuery->have_posts()) {
$pagesQuery->the_post() ;
the_title() ;
echo '<br>' ;
}
}
}
What this is doing is it is getting a structure of the parent pages like this image shows below
This is currently getting all the parent pages which is fine however I also need it to display that parent pages children under it. so for example it would be something like this;
Any help with this would be much appreciated if I can give anything else to assist in what I am trying to achieve please do let me know.
You can use wp_list_pages() and pass in the parent page ID with child_of to get its children. You can refer to the WP docs for more info.
So that'd look something like
wp_list_pages(array(
'child_of' => $parentId
));
Probably best to use get_pages()
function getPagesHierarchy() {
$pages = get_pages(array('parent' => 0));
foreach ( $pages as $page ) {
echo $page->post_title;
echo '<br>' ;
$child_pages = get_pages(array( 'child_of' => $page->ID));
foreach ( $child_pages as $child_page ) {
echo $child_page->post_title;
echo '<br>' ;
}
}
}

How to check if wp_query results found any custom post_type?

In my WordPress v5.8.1, I have the below query in taxonomy.php to get the list of posts.
$args = array(
'post_type' => array('song', 'dance'),
'post_status' => 'publish',
'posts_per_page' => 10,
);
query_posts($args);
The query return posts from both post_type's.
I would like to create a menu in the same page, where I want to check if the query results has found posts from a specific post_type. The menu looks something like this.
This taxonomy has posts from Song, Dance (if found posts from both post_type's), or
This taxonomy has posts from Song (if found posts from Song post_type only)
Have tried the below within the loop:
$song_count = wp_posts_count('song')->found_posts;
$dance_count = wp_posts_count('dance')->found_posts;
if ($song_count=>0 {
/** code goes here **/
}
Above is returning the count from entire WordPress, not just from current taxonomy.
You can stock result in variable, but did I understand the question correctly?
$args = array(
'post_type' => array('song', 'dance'),
// or 'post_type' => get_post_type($post->ID),
// conditions are no longer necessary
'post_status' => 'publish',
'posts_per_page' => 10,
);
$results = query_posts($args);
if($results) {
$count = 0;
$current_post_type = get_post_type($post->ID);
$current_post_type_name = get_post_type_object(get_post_type())->labels->singular_name); // ajust with 2 variables for multiple results
foreach($results as $result) {
// if request is in a single custom post
if($result->post_type == $current_post_type) {
$count++;
}
}
if($count > 0) {
echo $count . $current_post_type_name;
}
}
else {
// no results
}

WP Query and ACF fields

Im new to WP Query and ACF custom fields. I want to write a code that will show first 3 results from the calculation of the total_score custom field. I have managed to short by the total score but I want to show the title and permanlink of the first 3 posts so the visitor will click and go to the post. Any help will be much appreciated. My code so far :
$args = array(
'posts_per_page' => -1,
'post_title' => true,);
$all_posts = array();
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ):
while ( $the_query->have_posts() ): $the_query->the_post();
// Get all fields
$fields = get_fields();
// Push each $fields array into the $all_posts array
array_push($all_posts, $fields);
endwhile;
// Restore original Post Data
wp_reset_postdata();
// Print the result here and do what you choose
print_r($all_posts);
endif;
if(isset($_POST['place']))
{ // start the loop
$q1=$_POST["place"];
//CORECT CODE !!!!
foreach($all_posts as &$value) {
if ($value['question1']==$q1){
$value['total_score']=$q1;
}
} } //end question 1
// question 2
if(isset($_POST['home']))
{ // start the loop
$q2=$_POST["home"];
foreach($all_posts as &$value) {
if ($value['question2']==$q2){
$value['total_score']=$value['total_score']+$q2;
}
//echo $value['total_score']."<br>"; }
//echo "Q2"."<br>";
//print_r($all_posts);
} //end question 2
// question 3
if(isset($_POST['hours']))
{ // start the loop
$q3=$_POST["hours"];
//CORECT CODE !!!!
foreach($all_posts as &$value) {
if ($value['question2']==$q3){
$value['total_score']=$value['total_score']+$q3;
}
}
//echo "Q2"."<br>";
} //end question 3
// shorting by total_score
function sortByOrder($a, $b) {
return $b['total_score'] - $a['total_score'];
}
usort($all_posts, 'sortByOrder');
//print_r($all_posts);
foreach($all_posts as &$value) {
echo $value['total_score']."<br>";
}
Please replace your code with only this code. It's give you only 3 post and your total_score ASC or DESC
and Replace data in as per comment
Let me know if any Query
<?php
$args = array(
'post_type' => 'portfolio', // your post type name
'orderby' => 'meta_value_num', // if total_score is string then use it - meta_value
'meta_key' => 'total_score', // your meta key name ( total_score custom field )
'posts_per_page' => 3,
'order' => 'ASC' // ASC or DESC
);
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) :
while ( $loop->have_posts() ) : $loop->the_post();
echo ''.get_the_title().'';
endwhile;
endif;
wp_reset_postdata();
You could look at using your $args variable to both limit and filter the results of WP_Query. Setting your 'posts_per_page' => 3. This means only 3 posts will be returned in the query.
However, as you are fetching all of the posts and using usort to sort them, you can swap this out to use this resource to help you query using a custom field. This will reduce the amount of work is needed to compile the posts you require.
You can then use the final result to loop over the 3 posts and output your title & permalink.

How do i check if a wordpress query has more posts?

So i am using ajax to filter and load posts into a container. I want to limit the amount of posts to 6 at a time and add a load more button underneath if there are more than 6 posts, but i don't want to add pages because i have a few containers on the same page that i'm using this same treatment for and my understanding is pages would add a /page-1 or something like that to the url (am i wrong?).
Either way, i just want to know how to check if there are more posts that fit this criteria so i can show the load more button, and then when the load more button fires how do i just load 6 more. Do i have to keep a page variable somewhere? or is there another smarter way.
Here is my query
function ajax_filter_get_posts( $category, $tag )
{
$category = $_POST['category'];
$tag = $_POST['tag'];
if($category)
{
$category_args = array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => $category
);
}
$args = array(
'posts_per_page' => 6,
'post_status' => 'publish',
'tag' => implode(",",$tag),
'tax_query' => array(
$category_args,
),
'category__in' => array(187,186,183,182,184),
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post();
$output = post_factory($post);
$result['response'][] = $output;
$result['status'] = 'success';
endwhile; else:
$result['response'] = '<h2>No posts found</h2>';
$result['status'] = '404';
endif;
$result = json_encode($result);
echo $result;
die();
}
I know this post is about a year old, but in case anyone else needs an answer, here's the solution I'm implementing. I'm using Ajax to pull in a wp_query from a PHP file. The output from that file replaces the content of a div on my page. This is only the relevant code, not my complete code.
On click of the load more button, I use jQuery to count the number of posts on the page and put that count into a variable. Posts have a unique class assigned to them.
current = $('.item').length;
I send the post count to the PHP file using Ajax.
$.get(functions_home.url, { offset: current }, function(data) {
$('.grid').html(data);
}
I pull the post count from jQuery into a variable in the PHP file, and then use that variable to set the wp_query "offset" in $args.
$offset = $_GET['offset'];
$args = array (
'offset' => $offset
);
Once the query ($query) runs, I use $query->found-posts to tell me the total number of relevant posts, and I put that in a variable.
$total = $query->found_posts;
I make a div in my PHP file and use the found posts variable so that it's populated with the total number of relevant posts. I use CSS to hide that div, so that it's never visible on the website.
<div id="total"><?php echo $total; ?></div>
#total {
display: none;
}
I use jQuery to find that div on the page, and get the text from it, which is the total number of relevant posts. I put that in a variable.
total = $('#total').text();
I use jQuery to check whether the number of posts on the page is equal to the total number of posts, and, if it is, I hide the load more button. For my particular situation, I check in both the initial Ajax load and the Ajax call that fires when the load more button is clicked.
current = $('.item').length;
total = $('#total').text();
if ( current == total ) {
$('.load-more').css({
display: 'none'
});
}
I don't know if this is the best solution, or even a good solution, but it's what I've figured out to do, and it's working for me so far.
WP_Query has a parameter max_num_posts which will tell you how many pages in total the query have.
Inside the callback function you can check if there any more pages left in a query and send the value in response. Than you will be able to hide/show "load more" button with JS function based on that value. You can something similar to this:
function ajax_filter_get_posts( $category, $tag, $paged = 1 )
{
$paged = $_POST['paged']; // Pass a number of a page that you want to retrieve. Default is page #1
$category = $_POST['category'];
$tag = $_POST['tag'];
if($category)
{
$category_args = array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => $category
);
}
$args = array(
'posts_per_page' => 6,
'paged' => $paged, // pass required page number to WP_Query
'post_status' => 'publish',
'tag' => implode(",",$tag),
'tax_query' => array(
$category_args,
),
'category__in' => array(187,186,183,182,184),
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post();
$output = post_factory($post);
$result['response'][] = $output;
$result['status'] = 'success';
endwhile; else:
$result['response'] = '<h2>No posts found</h2>';
$result['status'] = '404';
endif;
// Check if there are any more pages to query and pass the boolean value in response
$result['more_pages'] = ( ( $query->max_num_pages - $paged ) > 0 ) ? true : false;
$result = json_encode($result);
echo $result;
die();
}

How do I Split Up A Wordpress Query?

Ive been looking all over web i even tried to hire freelancer for help on this but had no luck. While searching i found this how to get popular posts fro selected categories in wordpress? & http://www.queness.com/code-snippet/6546/how-to-display-most-popular-posts-from-a-specific-category-in-wordpress and thats basically what i want but i want the information i get from it split up so i can rank the post.
<?php
$args=array(
'cat' => 3, // this is category ID
'orderby' => 'comment_count',
'order' => 'DESC',
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 6, // how much post you want to display
'caller_get_posts'=> 1
);
$my_query = null;
$my_query = new WP_Query($args);
if( $my_query->have_posts() ) { ?>
<ul>
<?php while ($my_query->have_posts()) : $my_query->the_post(); ?>
<li><?php the_title(); ?></li>
<?php endwhile; ?>
</ul>
<?php }
wp_reset_query(); ?>
With that code it gets the most popular post by comments and what i want to do is basically take the results and add a rank to it like example below.
#1 - post 1
#2 - post 2
#3 - post 3
#4 - post 4
#5 - post5 last post
thanks in advance for any help
May be this idea will help you.
Use get_comments_number( $post_id ) function
To get number of comment and then do a if else loop for displaying rank.
$num_comments = get_comments_number(); // get_comments_number returns only a numeric value
if ( comments_open() ) {
if ( $num_comments == 0 ) {
$rating= 0 ;
} elseif ( $num_comments > 1 ) {
$rating= 1 ;
} else {
$rating= 0 ;
}
}
Thanks
By your current question I understand the following:
You want to query from the WP database posts that have the most comments.
You want to display to visitors a ranking for those received posts. The ranking is determined by the amount of comments post has.
So your result could be:
1 Post A (comment count 500)
2 Post B (Comment count 499)
3 Post Z (Comment count 200)
This is how I would do it:
<?php
function get_popular_posts()
{
$sql="SELECT comment_count, guid AS link_to_post, post_title
FROM wp_posts
WHERE post_status = "publish" AND post_type = "post"
ORDER BY comment_count DESC
LIMIT 5"
return $wpdb->get_results($sql, OBJECT)
}
$post_objects = get_popular_posts();
$i = 1;
foreach($post_objects as $object)
{
echo 'Post: ' . $i . '#' . ' ' . $post_title . ' ' . $link_to_post . ' ' . $comment_count;
$i++;
}
?>
Haven't tested the code. But it should take five "top posts" from the database. Left in the comment_count for explanatory reasons.

Categories