Order WP_Query by meta and post date - wordpress

I'm currently working on a small blog which has a sidebar that displays all "special projects".
"Special projects" is just a category, the sidebar will only display 4 posts at a time which are filtered by post date, but I also have a custom meta box to allow the user to feature posts.
These featured post should show up on the top of the special projects.
Right now my query is like this:
new WP_Query("showposts=" . $instance['num'] . "&cat=" . $instance["cat"] . "&order=ASC&order_by=date")
And I can get the featured meta data like this:
$featured = get_post_meta($single_cat_post->ID, 'soy_featured_post', true);
But how could I integrate this inside the WP_Query?

First of all, 'showposts' has been replaced by 'posts_per_page' when using WP_Query. I've corrected that in your code. Also, within a loop you should just be able to use $post->ID instead of $single_cat_post->ID.
I would use two loops. Set your paramaters, then in the first loop include a condition to check for the meta value, reset the query, then do another loop and include a condition that checks for the meta value and outputs nothing if it exists.
In the first query, I added a check to see how many posts are returned by the first loop. Then using that value (subtracted by 4) I calculated a variable to use for posts_per_page in the second loop. Then I added a conditional to only run the loop if the result is greater then 0.
This is untested, but it should work or at least put you on the right path!
<?php
$args = array(
'posts_per_page' => 4,
'meta_key' => 'soy_featured_post',
'cat' => $instance["cat"],
'orderby' => 'date',
'order' => 'ASC'
);
$special_post_query = new WP_Query( $args );
$special_posts_found = $special_post_query->found_posts;
if ($special_post_query->have_posts()) :
while( $special_post_query->have_posts() ) : $special_post_query->the_post();
// POST WITH META VALUE OUTPUT
the_title();
endwhile;
endif;
wp_reset_query();
$second_loop_posts_per_page = 4 - $special_posts_found;
if ($second_loop_posts_per_page > 0) {
$args = array(
'posts_per_page' => $second_loop_posts_per_page,
'cat' => $instance["cat"],
'orderby' => 'date',
'order' => 'ASC'
);
if ($special_post_query->have_posts() ) :
while( $special_post_query->have_posts() ) : $special_post_query->the_post();
// Condition to test for NO meta value
if (get_post_meta($post->ID, 'soy_featured_post', true) == null) {
// CODE
the_title();
} else {
// Don't print anything because the meta value exists
}
endwhile;
endif;
wp_reset_query();
} ?>

Related

Sticky posts not showing when using category filter

I am trying to show a specific category post on my home page and in which 1 post is sticky that will appear first but its not working.
I have noticed when I try to show all posts, then sticky post shows first. When I try to show a specific category then its not showing first.
Here is my code:
$sticky = get_option( 'sticky_posts' );
$args = array( 'posts_per_page' => intval($blogtoShow),
'post_status'=>'publish',
'post_type'=>'post',
'cat' => $cattoShow,
'orderby'=>'date',
'post__in' => $sticky);
$the_query = new WP_Query( $args );
if ($the_query->have_posts()) :
while( $the_query->have_posts() ) : $the_query->the_post();```
You're looking for the following:
ignore_sticky_posts (boolean) – ignore post stickiness (available since version 3.1, replaced caller_get_posts parameter). false (default): move sticky posts to the start of the set. true: do not move sticky posts to the start of the set.
If you're using a pre-made theme the default might have been modified.
You should add this to your arguments array: 'ignore_sticky_posts' => 0.
A comma should separate each arguments. (Not tested but should work)
More info on the worpress query: https://developer.wordpress.org/reference/classes/wp_query/
----------
EDIT 1.1: I think you need to display a specific template for the sticky (as it's not considered a normal post). At the begining of your loop can you try the following?
$sticky = get_option( 'sticky_posts' );
$args = array(
'posts_per_page' => 3,
'post__in' => $sticky,
);
$query = new WP_Query( $args );
if ( $sticky[0] ) {
// insert sticky template...
} else {
// insert posts template...
}

Order post by date and custom meta

I have 2 custom meta one for the start date of my event and one for the end date of my event and I need to order my events according to the start date and to remove them when the end date is over.
Meta:
Start date: date_de_levenvement
End date: date_de_fin
Here is my loop:
<?php query_posts( 'post_type=agenda&meta_key=date_de_fin&meta_compare=>=&meta_value=' . $todaysDate . '&orderby=meta_value&order=ASC'); ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php
$date = get_field('date_de_fin');
$newDate = date("d/m/Y", strtotime($date)); ?>
Just need to change the query but I don't know how to use 2 parameters with the meta value. &orderby=meta_value needs to be something like &orderby="date_de_levenement"
I would actually use the more robust WP_Query object to accomplish this task. More specifically, you can see the section called Custom Field Parameters and see the example titled Multiple Custom Field Handling. You can create your arguments array like so:
$args = array(
'post_type' => 'agenda',
'meta_key' => 'date_de_levenvement',
'meta_query' => array(
array(
'key' => 'date_de_fin',
'value' => $todaysDate,
'compare' => '>='
)
),
'orderby' => 'meta_value_num',
'order' => 'ASC'
);
$your_custom_query = new WP_Query($args);
// The Loop
if ( $your_custom_query->have_posts() ) {
while ( $your_custom_query->have_posts() ) {
$your_custom_query->the_post();
// your code goes here
}
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();
Explanation
The meta_query element is an array of arrays which means you can even filter against multiple meta (custom field) properties if you wish. Notice that I included the meta_key element. This is what will allow you to sort by your start date. Whereas the key element of the meta_query element is what will filter your end date posts. (In this situation, post types named agenda will only be included if their date_de_fin is greater than or equal to "today".
[edit]
Note that the "today" date should be formatted in SQL format like so:
<?php $todaysDate = date('Y-m-d'); ?>
Hope this helps a bit. Have fun!

Let users sort posts in Wordpress

I’d like to create a page for filtering posts based on a number of criteria.
I can work with wp_query and deliver posts quite easily, my problem is that I can’t figure out (nor can I find any answers online about this, believe me I looked) how to let users do this.
Take this for example, returns the posts in order of price (custom field meta value) from highest to lowest with 33 posts.
<?php
$featuredPosts = new WP_Query( array(
'posts_per_page' => 33,
'meta_key'=>'Price',
'orderby' => 'meta_value_num',
'order' => DESC
) );
?>
<?php if ( $featuredPosts->have_posts() ) : ?>
<?php while ( $featuredPosts->have_posts() ) : $featuredPosts->the_post(); ?>
<article <?php post_class('item-post block'); ?> id="post-<?php the_ID(); ?>">
<h2 class="price-title"><?php the_title(); ?> </h2>
</article> <!-- end div post -->
<?php endwhile; wp_reset_query(); ?>
<?php endif; ?>
Now, even after reading and googling, I’ll be damned if I can figure out how I’d implement this on the front end for users to filter posts.
I mean, I know you can append to the URLs in Wordpress to alter the order of posts, but in this context I’m totally lost.
I tried this, but it doesn't work.
<?php
$by_price = esc_url(add_query_arg(array(
'meta_key' => 'price',
'orderby' => 'meta_value_num',
'order' => ASC
)));
$by_date = esc_url(add_query_arg(array(
'orderby' => 'date',
'order' => DESC
)));
?>
<ul>
<li>Order by price</li>
<li>Order by date</li>
</ul>
What I’m trying to achieve is actually quite simple as well, let the user choose the category, choose the price range (guessing I’d write something in JQuery to deliver a value into an field), set the number of results they’d like to be returned.
I’ve tried googling everything under the sun I can think of for this, no dice.
Try Simple Custom Post Order plugin.
It is using AJAX and JavaScript, you don’t have to load anything else. You have to just drag and drop the posts.
OK, I update the code to make it clear:
---I do not think meta_key would be auto-pickup---
functions.php
...
$whitList = array(
'price' => array(
'posts_per_page' => 33,
'meta_key'=>'price',
'orderby'=>'meta_value_num',
'order' => ASC
),
'date' => array(
'posts_per_page' => 33,
'orderby'=>'date',
'order' => DESC
)
);
...
Your first loop php:
<?php
gloabl $whitList; //to use the $whitList in your functions.php.
$aryQuery = $whitList[$_REQUEST['orderby']] ? $whitList[$_REQUEST['orderby']] : $whitList['price'];
$featuredPosts = new WP_Query( $aryQuery );
....
....
?>
For your list page:
<ul>
<?php
gloabl $whitList; //to use the $whitList in your functions.php.
foreach( $whitList as $orderby => $aryOrderBySettings){
?>
<li> Order by <?php echo $orderby;?></li>
<?php
}
?>
</ul>
Using $_GET parameters is the way to go here. First of all you'll want to allow your visitors access to these add these variables. The link approach is fine, overall, so we can generate augmented links by using the add_query_arg to tack on extra parameters to the current URL.
<?php
$urla = add_query_arg( 'sort' => 'price', 'asc' => '1' );
$urld = add_query_arg( 'sort' => 'price', 'asc' => '0' );
?>
Sort by price (asc)
Sort by price (desc)
When clicked, the tacked on variables can thus be detected:
<?php
// Get an allowed sort variable and the order
$sort = isset( $_GET['sort'] ) && in_array( $_GET['sort'], array( 'price' ) ) )
? $_GET['sort'] : null;
$order = isset( $_GET['asc'] ) && $_GET['asc'] == '0' ? 'DESC' : 'ASC';
?>
Now you would augment your main query with the data you just retrieved. If you're using the default way of querying posts on a page you should be able to get away with query_posts, although it is not recomended. And, if you're using a custom loop, simply inject the new arguments into it:
<?php
$args = array();
switch ( $sort ):
case 'price':
$args['order'] = $order;
$args['orderby'] = 'meta_value_num';
$args['meta_key'] = 'price';
break;
default:
break;
endswitch;
$defaults = array( 'posts_per_page' => 33 );
$query = new WP_Query( wp_parse_args( $args, $defaults ) );
?>
You can add more variables, by creating more URLs and buttons to press, and more cases in the switch statement to extend the basic example above.
The first piece of code would go wherever you want your buttons to appear. The second piece of code goes before the third one, which goes before outputting the results.

how to retrieve WP_Query without ordering by date

I want to use
$ps = "9126,8955,8554,8620,8825,8912,8937,8813,9054,9022";
$recent = new WP_Query( array('post__in' => explode(',', $ps)) );
to retrieve posts by ID, I do and the result ordered by publish date but I want to retrieve in same of IDs in this example in this order:
9126,8955,8554,8620,8825,8912,8937,8813,9054,9022
Personally, if the order of posts as well as your ID numbers are going to be that strict, I would probably avoid using WP_Query:
<?php
$ids = array(9126,8955,8554,8620,8825,8912,8937,8813,9054,9022);
foreach($ids as $id)
{
$post = get_post($id);
setup_postdata($post);
?>
<!-- YOUR HTML HERE -->
<?php
}
?>
Otherwise, since Posts do not have any kind of Menu Order option like Pages do, you will probably have to set a Custom Field and give it a value (with lower numbers taking priority over higher numbers). Then you can do something like this:
<?php
$ids = array(9126,8955,8554,8620,8825,8912,8937,8813,9054,9022);
$recent = new WP_Query(array('post__in' => $ids, 'orderby' => 'meta_value_num', 'meta_key' => 'postOrder', 'order' => 'ASC'));
?>
This second option is untested and I can't guarantee it will work right off the bat, but it should get you started. Good luck.
in the future in wordpress 3.5 you can use: 'orderby'=>'post__in'

Wordpress Loop: Insert Content After Specific Post Number

I am wondering if there is a way to insert a block of content after a specific post number in my Custom Post Loop.
Essentially, I want to say:
After the 2 most recent mosts, insert this block of code.
If that can be done, I would also be interested in knowing if something like this is achievable:
Start a Custom Post Loop that excludes a specific Post Format (or Category), but after every 2 posts, insert 1 of the excluded Post Formats.
Thanks for any assistance.
<!-- #STICKY-POSTS |begin| -->
<section id="sticky-posts">
<?php
$args = array( 'post_type' => 'portfolio', 'posts_per_page' => 2, 'cat' => '8' );
$custom_query = new WP_Query( $args);
while($custom_query->have_posts()) : $custom_query->the_post();
get_template_part('format', 'standard');
endwhile;
?>
Do something like this:
<!-- #STICKY-POSTS |begin| -->
<section id="sticky-posts">
<?php
$args = array( 'post_type' => 'portfolio', 'posts_per_page' => 2, 'cat' => '8' );
$custom_query = new WP_Query( $args);
$x = 0;
while($custom_query->have_posts()) : $custom_query->the_post();
if($x==2) {
display your thing here.
$x=0;
}
get_template_part('format', 'standard');
$x++
endwhile;
?>
Unless I botched something, x=0 will turn 1 at first normal post, 2 at second normal post then return true on the if statement, got back to 0 and rinse repeat.

Resources