Let users sort posts in Wordpress - 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.

Related

WordPress Adding Variables to Loop Arguments

I have a custom post-type call Called 'Sectors' and another post type called 'Challenges' The challenges post type has a taxonomy called 'sectortype' - which has the same names as the sectors.
I created a page called 'single-sector.php' On that page displays a loop that includes challenges related to that sector.
When I write the loop for displaying challenges, how do I make the 'sectortype' => 'advanced-education' a variable so it will work on other single sector pages?
Here's what I have for the loop...
<?php $challenge_args = array(
'post_type' => 'challenge',
'sectortype' => 'advanced-education', //Need Help Here
);
// create a new instance of WP_Query
$challenge_query = new WP_Query( $challenge_args );
?>
<?php if ( $challenge_query->have_posts() ) : while ($challenge_query->have_posts() ) : $challenge_query->the_post(); // run the loop ?>
Get Custom posts by custom taxonomy terms :
<?php
$terms = get_terms('sectortype');
$challenge_args = array(
'post_type' => 'challenge',
'publish_status' => 'published',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'sectortype',
'field' => 'slug',
'terms' => $terms[0], //whichever term you want to select
),
),
);
// create a new instance of WP_Query
$challenge_query = new WP_Query( $challenge_args );
?>
<?php if ( $challenge_query->have_posts() ) : while ($challenge_query->have_posts() ) : $challenge_query->the_post(); // run the loop ?>
DISPLAY IN SEPARATE PAGES
TO display the posts in separate pages as you mentioned in the comment, you have to do the following:
Create Separate Page Links:: (use on page as navigation items)
<?php $categories = get_terms('sectortype');?>
<ul>
<?php foreach( $categories as $key => $c ):?>
<?php $cat_link = get_term_link( $c->term_id );?>
<?php $term_title= single_term_title('', false);?>
<li class="<?php echo ($c->name == $term_title )?'active':'';?>"><?php echo $c->name;?></li>
<?php endforeach;?>
</ul>
Create a file in theme directory (actually an archive template for taxonomy terms) with the filename 'taxonomy-sectortype.php'.
On that template, get the posts from the usual loop without using any queries and you will get the respective posts.

How to hook in a custom query to the loop with Wordpress

I want to create a loop and query posts by their author role. And display the results of a search term based on the authors role.
I've tried creating a function to alter the query's where clause:
$ids = get_users(
array(
'role' => 'administrator' ,
'fields' => 'ID'
)
);
$query = new WP_Query(
array(
'author__in' => $ids,
)
);
// If the query has data
if($query->have_posts() ) :
// Post loop
while ($query->have_posts() ) :
// Setup post data
$query->the_post();
?>
<!-- Do HTML markup and template tags here, eg. the_content(), the_title() etc.. -->
<h1>You're a post from administrator - <?php the_title(); ?></h1>
<?php get_template_part( 'template-parts/content', 'search' ); ?>
<?php
endwhile;
// End "If the query has data"
endif;
I'm trying to add a WP_Query to the loop but this is where I get stuck with the results not getting filtered by role so I'm fairly certain I must be implementing this wrong - this is the first time I've tried to do something like this so sorry if it's a dump question but I can't find an answer to my question so if anyone can point me in the right direction that would be amazing!
Any advice welcome, thank you!
You can try the posts_where
hook.
UPDATE:
Why don't you use the default WP_Query author arg instead hook.
You query will be :
$ids = get_users(
array(
'role' => 'administrator' ,
'fields' => 'ID'
)
);
$query = new WP_Query(
array(
'author__in' => $ids,
)
);

Order WP_Query by meta and post date

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();
} ?>

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 - Custom taxonomy page of custom post type listing by terms

I have a taxonomy-taxonomy.php page that needs to look like so:
CUSTOM POST TYPE TITLE (RESOURCES)
Custom Taxonomy 1 (Resource Types)
Resource Type Term 1 (White Papers)
White Paper post 1
White Paper post 2
White Paper post 3
Resource Type Term 2 (Videos)
Videos post 1
Videos post 2
Videos post 3
Tried to make sense of all the new documentation for Wordpress 3.0, but it only made me more confused as it seems to be mixed up with 2.8.
It's not necessary to transform the object to an array, you can perfectly work with the object without too much hassle. What is curious (at least for me), is that you get something like this:
Array
(
[0] => stdClass Object
(
[term_id] => 7
[name] => Magister comunicaciones aplicadas
[slug] => magister-comunicaciones-aplicadas
[term_group] => 0
[term_taxonomy_id] => 7
[taxonomy] => linea-de-estudio
[description] =>
[parent] => 0
[count] => 4
)
[1] => stdClass Object
(
[term_id] => 8
[name] => Engagement marketing
[slug] => engagement-marketing
[term_group] => 0
[term_taxonomy_id] => 8
[taxonomy] => linea-de-estudio
[description] =>
[parent] => 0
[count] => 5
)
)
It's basically, an array of objects, so you've to treat them that way. For example if I want the name of the the first one:
$myterms = get_terms('taxonomy-name', 'orderby=none&hide_empty');
echo $myterms[0]->name;
If you need to iterate through the elements, you still can use foreach();.
foreach ($myterms as $term) { ?>
<li><?php echo $term->name; ?></li> <?php
} ?>
That way you can post the articles from your taxonomy.
For the custom post types, you'll have to create a loop like this:
$args = array(
'post_type' => 'post-type-name',
'taxonomy' => 'term'
//for example
//'resources' => 'videos'
);
// assigning variables to the loop
global $wp_query;
$wp_query = new WP_Query($args);
// starting loop
while ($wp_query->have_posts()) : $wp_query->the_post();
the_title();
blabla....
endwhile;
Then you can create multiple loops each of one for each taxonomy/term :).
If you want to get even more fancy (don't want to repeat yourself a hundred times) you can include the second loop inside the first one and assign variables to the taxonomy (resources ie) and the terms it has (videos) (from your example only the last one). The idea is that you would have a normal (typical) wordpress loop restricted to the custom post-type and each one of the terms.
foreach ($myterms as $term) : ?>
<li><?php echo $term->name; ?></li> <?php
$term_name = $term->slug;
$args = array(
'post_type' => 'post-type-name',
'taxonomy' => "$term_name"
);
// assigning variables to the loop
global $wp_query;
$wp_query = new WP_Query($args);
// starting loop posting only
while ($wp_query->have_posts()) : $wp_query->the_post();
the_title();
blabla....
endwhile;
endforeach; ?>
Obviously you can do the inverse thing too, create the normal loop for a single-template custom type (it's looks like you have only one), and inside includes all the custom terms.
Not very elegant, but that's the best way I can came up with it :P. Hope that someone can understand this, sounds confusing.
Maybe could it be possible with some callback function?.
Hey manon1165 , I actually just accomplished this. Was a huge pain, hopefully my code snippet will help!
I made a custom page template. And did something along the lines of
<?php $categories = get_terms('taxonomy-name', 'orderby=name&hide_empty=0'); $cats = object_to_array($categories); ?>
Now, just print_r($cats) and you will see the array of the categories.
You will need to convert the object to an array, I did so with.
function object_to_array($data)
{
if(is_array($data) || is_object($data))
{
$result = array();
foreach($data as $key => $value)
{
$result[$key] = object_to_array($value);
}
return $result;
}
return $data;
}
I did
<ul id="cat-list">
<?php foreach($cats as $cat) { ?>
<li><?php echo $cat['name']; ?> (<?php echo $cat['count']; ?>)<br><?php echo $cat['description']; ?></li>
<?php } ?>
</ul>
Hope that helps!
This worked fine for me:-
<?php
$custom_terms = get_terms('custom_taxonomy');
foreach($custom_terms as $custom_term) {
wp_reset_query();
$args = array('post_type' => 'custom_post_type',
'tax_query' => array(
array(
'taxonomy' => 'custom_taxonomy',
'field' => 'slug',
'terms' => $custom_term->slug,
),
),
);
$loop = new WP_Query($args);
if($loop->have_posts()) {
echo '<h2>'.$custom_term->name.'</h2>';
while($loop->have_posts()) : $loop->the_post();
echo ''.get_the_title().'<br>';
endwhile;
}
}
>?

Resources