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.
Related
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
}
I have found this question:
Wordpress outside loop sort by category and time
But there is not a lot of context provided in the question or answer to know if it is applicable to me. I am using the popular genesis framework and a child theme. I don't want to modify any core WP files because they would be overwritten on updates. I think this can be done through my functions.php or front-page.php file.
I have 25 posts listed at a time. Within those 25 posts, I would like to have any post that is from category one be listed on top and those from category two listed afterwards. Within the category one and category two loops, the posts would be listed by time of entry as normal.
What would be the best way to do this?
SDS
You need two loop one for categories and one for posts.
So you can try this type of code
/*category args for listed according to name in assending order*/
$category_arg = array(
'orderby' => 'name',
'order' => 'ASC'
);
$all_cat = get_categories($category_arg);
/*Loop for all category*/
foreach ($all_cat as $key => $cat) {
/*Query for post of perticular category with orderby posted date*/
$args = array(
'cat' => $cat->cat_ID,
'posts_per_page' => -1,
'orderby' => 'date',
'order' => 'DESC',
) ;
query_posts( $args );
echo '
<div class="one-category-block">
<h1>'.$cat->cat_name.'</h1>';
echo '<ul>';
while ( have_posts() ) : the_post();
echo '<li>';
the_title();
echo '</li>
';
endwhile;
echo '</ul>
</div>';
wp_reset_query();
}
Try this type of code , then let me know the result.
Thanks
All right. You won't be able to do that on the query directly, I'm afraid.
However, it's still easy to do. First, get the posts out of the query into an array:
$posts = array();
while ( have_posts() ) {
the_post();
array_push($posts, $post);
}
Then sort that array:
usort($posts, function($a, $b) {
if(has_term("mycategory", "mytaxonomy", $a->ID) && !has_term("mycategory", "mytaxonomy", $b->ID)) return -1;
if(!has_term("mycategory", "mytaxonomy", $a->ID) && has_term("mycategory", "mytaxonomy", $b->ID)) return 1;
return $b->post_date - $a->post_date;
});
I've made it so that posts having mycatgegory in the mytaxonomy taxonomy will be on top, but generally sorted by post date.
Then just use a regular foreach loop to iterate over the (now sorted) posts
foreach($posts as $post) {
setup_postdata($post);
// continue outputting the posts here
}
wp_reset_postdata();
setup_postdata() is there to make sure that you can use get_the_ID(), get_permalink() et cetera without changing your code.
I have two WordPress post types the normal 'post' and a custom post type called 'notes'. I want to combine both and sort them by date. I managed to find the combine query and that's working fine. The problem is I'd like to have different styling for notes. I thought I could do a wordpress if_singlular('notes') to try and target it.. but I'm guessing it's getting lost when the merge happens.
Does anyone know how I could achieve this functionality?
Many thanks!
My php:
<?php
// An example of creating two separate WP queries, combining the results,
// sorting by date and formatting the results for us in a loop like a regular query.
// order the posts by date in descending order (should go in functions.php to keep things tidy)
function order_by_date( $a, $b )
{
return strcmp( $b->post_date, $a->post_date );
}
// get the posts for the first query
$q1_args = array(
'post_type' => 'post',
'posts_per_page' => -1,
'post_status' => 'publish'
);
$q1_posts = get_posts( $q1_args );
// get the posts for the second query
$q2_args = array(
'post_type' => 'notes',
'posts_per_page' => -1,
'post_status' => 'publish'
);
$q2_posts= get_posts( $q2_args );
// Merge the post arrays together, and sort by date using the order_by_date function
$final_posts = array_merge( $q1_posts, $q2_posts );
usort( $final_posts, 'order_by_date' );
// Loop over the posts and use setup_postdata to format for template tag usage
foreach ( $final_posts as $key => $post ) {
setup_postdata( $post );
// Now we can use template tags as if this was in a normal WP loop
foreach ( $final_posts as $key => $post ) {
setup_postdata( $post );
// Now we can use template tags as if this was in a normal WP loop
echo '
<article class="item shortNote">
<div class="snMeta clearfix">
<img src="'.get_bloginfo('template_url').'/assets/images/sn-icon.png" alt="Short Note" />
<span class="metaDate">'. get_the_date('M / d / Y').'</span>
<strong>Short Note</strong>
</div>
<h2>'.get_the_title().'</h2>
</article>';
}
}
?>
Ok so this should do it:
<?php
// An example of creating two separate WP queries, combining the results,
// sorting by date and formatting the results for us in a loop like a regular query.
// order the posts by date in descending order (should go in functions.php to keep things tidy)
function order_by_date( $a, $b ) {
return strcmp( $b->post_date, $a->post_date );
}
// get the posts for the first query
$q1_args = array(
'post_type' => 'post',
'posts_per_page' => -1,
'post_status' => 'publish'
);
$q1_posts = get_posts( $q1_args );
// get the posts for the second query
$q2_args = array(
'post_type' => 'notes',
'posts_per_page' => -1,
'post_status' => 'publish'
);
$q2_posts= get_posts( $q2_args );
// Merge the post arrays together, and sort by date using the order_by_date function
$final_posts = array_merge( $q1_posts, $q2_posts );
usort( $final_posts, 'order_by_date' );
// Loop over the posts and use setup_postdata to format for template tag usage
foreach ( $final_posts as $key => $post ) {
$post_type = $post->post_type;
setup_postdata( $post );
// Now we can use template tags as if this was in a normal WP loop
<article class="item shortNote ' . $post_type . '">
<div class="snMeta clearfix">
<img src="'.get_bloginfo('template_url').'/assets/images/sn-icon.png" alt="Short Note" />
<span class="metaDate">'. get_the_date('M / d / Y').'</span>
<strong>Short Note</strong>
</div>
<h2>'.get_the_title().'</h2>
</article>';
}
?>
I just had to test it on my server to see if it works. So I added the $post_type variable that should return the post type, and then I just put that in your class in the <article> tag, so you can differentiate :)
Tip:
When in doubt what your loop outputs, always do print_r(). This will show you what you are dealing with (arrays, strings, objects) so you easily know what to target :)
Hope this helps.
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();
}
So I have done a bunch of looking around the web and couldn't find a solution for this...
Basically what I am trying to do is display a product loop of all the products the user has purchased in the store just like displaying normal products.
If you still don't understand maybe this will help you get what I mean..
Here is the example product loop on the WooCommerce documentation...
<ul class="products">
<?php
$args = array(
'post_type' => 'product',
'posts_per_page' => 12
);
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) : $loop->the_post();
woocommerce_get_template_part( 'content', 'product' );
endwhile;
} else {
echo __( 'No products found' );
}
wp_reset_postdata();
?>
</ul><!--/.products-->
So what if I wanted to display basically this same exact product loop however filter it out so that it only displays products that the user has already purchased.
I honestly do not know where to go with this one and I am sure there are others that have done research on this in the past so maybe this will help out a bunch of people!
Thanks in advance!
There are at least two different approaches you can take to solve this problem.
The first is to get the product from each post, and then get the product ID from each product and then use an if statement to filter using wc_customer_bought_product or woocommerce_customer_bought_product (if you are using old WooCommerece).
The second is to pass the correct arguments to filter the WP_Query to only include orders purchased by a user and then filter products only in those orders. More information on the second approach is available at Get All User Orders and Products bought by user in WooCommerce based shop (archive.org).
An example of the first approach is something like
<!-- code started -->
<ul class="products">
<?php
$user_id = get_current_user_id();
$current_user= wp_get_current_user();
$customer_email = $current_user->email;
$args = array(
'post_type' => 'product',
'posts_per_page' => 12
);
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) : $loop->the_post(); $_product = get_product( $loop->post->ID );
if (wc_customer_bought_product($customer_email, $user_id,$_product->id)){
woocommerce_get_template_part( 'content', 'product' );
}
endwhile;
} else {
echo __( 'No products found' );
}
wp_reset_postdata();
?>
</ul><!--/.products-->
Kudos to Appleman1234 for providing two answers, both of which will work.
ApppleMan1234's first answer that he provided an example for is to loop through all products and then filter them by calling wc_customer_bought_product(). This certainly will work. If you have n products then you are going to make n+1 database queries.
His second suggestion is a link to a post written by Brajesh Singh who, on June 2, 2013, published a solution on fusedpress.com. The original post is no longer available. I found a cached copy at Google.
Brajesh Singh's solution queries the user's orders, then queries the order details, and last queries the product id in the order item's metadata. This solution then is always only 3 queries. Unless your shop only has 1 or 2 products, this solution is far better.
Here is a slightly edited version of Brajesh Singh's code.
/**
* Get all Products Successfully Ordered by the user
* #return bool|array false if no products otherwise array of product ids
*/
function so28362162_get_all_products_ordered_by_user() {
$orders = so28362162_get_all_user_orders(get_current_user_id(), 'completed');
if(empty($orders)) {
return false;
}
$order_list = '(' . join(',', $orders) . ')';//let us make a list for query
//so, we have all the orders made by this user that were completed.
//we need to find the products in these orders and make sure they are downloadable.
global $wpdb;
$query_select_order_items = "SELECT order_item_id as id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id IN {$order_list}";
$query_select_product_ids = "SELECT meta_value as product_id FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE meta_key=%s AND order_item_id IN ($query_select_order_items)";
$products = $wpdb->get_col($wpdb->prepare($query_select_product_ids, '_product_id'));
return $products;
}
/**
* Returns all the orders made by the user
* #param int $user_id
* #param string $status (completed|processing|canceled|on-hold etc)
* #return array of order ids
*/
function so28362162_get_all_user_orders($user_id, $status = 'completed') {
if(!$user_id) {
return false;
}
$args = array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $user_id,
'post_type' => 'shop_order',
'post_status' => 'publish',
'tax_query' => array(
array(
'taxonomy' => 'shop_order_status',
'field' => 'slug',
'terms' => $status
)
)
);
$posts = get_posts($args);
//get the post ids as order ids
return wp_list_pluck($posts, 'ID');
}
Combining that with a product loop from the question, plus a non-deprecated wc_get_template_part() and an addition of posts_per_page=-1 gives us
<ul class="products">
<?php
$args = array(
'post_type' => 'product',
'post__in' => so28362162_get_all_products_ordered_by_user(),
'posts_per_page' => -1
);
$loop = new WP_Query($args);
if($loop->have_posts()) {
while($loop->have_posts()) : $loop->the_post();
wc_get_template_part('content', 'product');
endwhile;
}
else {
echo __('No products found');
}
wp_reset_postdata();
?>
</ul><!--/.products-->
Not sure if this helps you out at all, but there is a plugin developed by WooThemes to support purchase history.