For many different reasons I was forced to deactivate the sticky posts function on WordPress. Still I need this function. This means that I need a workaround. I need to show a post on the top of the feed and I need it to be made as easily as possible for the user that is writing the post.
NOTE: I am using Visual Composer.
I thought that a workaround for this would be to add a new container via Visual Composer or a sidebar and call for a category. This new sidebar/container would then only be visible if there were any posts on that category. I have been searching for a function, query, plugin, etc to do this, but with no success.
I have found Featured Post Widget and Featured Category Widget but I don't think that they are what I need.
Hook with get_terms will display a terms/category only when it has posts
Add this code in WP theme's functions.php
E.g (domain.com/wp-content/themes/yourThemeName/functions.php )
add_filter('get_terms', 'get_terms_filter', 10, 3);
function get_terms_filter( $terms, $taxonomies, $args )
{
global $wpdb;
$taxonomy = $taxonomies[0];
if ( ! is_array($terms) && count($terms) < 1 )
return $terms;
$filtered_terms = array();
foreach ( $terms as $term )
{
$result = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts p JOIN $wpdb->term_relationships rl ON p.ID = rl.object_id WHERE rl.term_taxonomy_id = $term->term_id AND p.post_status = 'publish' LIMIT 1");
if ( intval($result) > 0 )
$filtered_terms[] = $term;
}
return $filtered_terms;
}
For ignore sticky posts on frontend set ignore_sticky_posts to true in main query
add_action('pre_get_posts', '_ignore_sticky');
function _ignore_sticky($query)
{
// Only for Front end
if (!is_admin() && $query->is_main_query())
$query->set('ignore_sticky_posts', true);
}
Related
In category.php I am using custom query to get posts:
<?php
$cat_id = get_query_var('cat');
$args = array(
'posts_per_page' => 2,
'orderby' => 'date',
'cat' => $cat_id
);
query_posts($args);
// the Loop
get_template_part('aa_HomeLoopMain');
?>
I am using get_query_var('cat') to get category post of current category and I think this would only give Category Posts of category id with $cat_id but not it's child category posts?
You are doing it wrong. Never ever use query_posts, it breaks the main query object, reruns queries and is slow which all negatively impacts on performance and SEO and other functions that relies on the main query. Also, if this is your main query, you should not be using a custom query at all, you should be using pre_get_posts to alter the main query before it executes.
get_query_var(cat) only returns the queried category, not its children.
You should remove the query_posts part and add the following to your functions.php
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin()
&& $q->is_main_query()
&& $q->is_category()
) {
$q->set( 'posts_per_page', 6 );
}
});
EDIT
You should query a total of 6 posts, I have updated my as such. You can try the following with your loop
if ( have_posts() ) {
while( have_posts() ) {
the_post();
if ( 1 <= $wp_query->current_post ) {
// Add your markup for column one, this will display 2 posts
} else {
// Add your markup for column two, this will display 4 posts
}
}
}
EDIT 2
For some reason I cannot post comments from my mobile, but I think you are using the code wrongly. I have updated my code to show the loop. It does work. If it does not, something else is breaking your page like query_posts
I am trying to create a series of pages that display the posts within a single category. To do this I use the following PHP code:
<?php
$args = array( 'category' => '$CATEGORY', 'numberposts' => 10000000000);
$myposts = get_posts( $args );
foreach($myposts as $post) :
setup_postdata($post);
?>
My problem is that the $CATEGORY does not seem to contain the category as a string. I have tried using both %s and $id but as I have not declared that it is the category id I am wanting it fails to work. The resulting output has been either an error or all the posts regardless of category.
What argument will convey the category string?
Below is a page illustrating the problem. This is a category page, meaning it should hold all the necessary info. If it was working it would only show the topmost post as it is the only post en site that has the "Press Release" category. Worth mentioning that I have another page just like it called "Dokument" and it displays the press release.
Page: http://www.skinwellness.se/category/pressrelease/
EDIT
I did not notice this before, but it seems that you are using the bundled theme twentythirteen. Simply delete the category.php from your child theme. If you have made changes to the parent theme directly, you should get a fresh copy of the theme, and create a child theme with all your modifications. Never make changes to a theme that you did not write. When such themes update, all you changes will be gone forever
You should then just need the pre_get_posts section in your child theme's functions.php to make everyone work
ORIGINAL ANSWER
You problem is purely your custom loop. As explained in the linked post, you should not be using custom queries in place of the main query on any type of archive page or on your home page
To solve this, revert back to the default loop. This is all you should have. No get_posts or foreach loops
if( have_posts() ) {
while( have_posts() ) {
the_post();
// Add your loop elements here like the_title() and the_content()
}
}
This should fix the problem that when you visit a category page, only the category been viewed will be viewed, no posts from other categories will be shown
Now, if you need to change anything on your category page, use pre_get_posts to do that. Make use of the is_category() conditional tag to target your category pages only. You can also target a specific category with this tag
Say for instance, you need to change the posts per page on you category page, as your case, display all posts with no pagination, you can do this in your functions.php
function so26589648_category_ppp( $query ) {
if ( !is_admin() && $query->is_category() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '-1' );
}
}
add_action( 'pre_get_posts', 'so26589648_category_ppp' );
If you need to for example change the order to ASC and need to order posts by author, you can do this
function so26589648_category_ppp( $query ) {
if ( !is_admin() && $query->is_category() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '-1' );
$query->set( 'order', 'ASC' );
$query->set( 'orderby', 'author' );
}
}
add_action( 'pre_get_posts', 'so26589648_category_ppp' );
You should see WP_Query for all available parameters to use
I am working with the Wordpress Query Object using the WP Types/Views Toolset.
http://wp-types.com
We built out the parametric search which allows the user to search through posts using various taxonomies. It works fine, it display search results as needed. BUT..
Most of the posts don't have featured images, we want to display posts with featured images at the top, and the featured imageless posts would go below.
I have a good head start on this as far as logic goes, just need a bit of help.
The code below allows me manipulate the query before rendering it to the user.
add_filter( 'wpv_filter_query_post_process', 'prefix_rearrange_by_thumbnail', 10, 3 );
function prefix_rearrange_by_thumbnail( $query, $view_settings, $view_id ) {
// sort posts by thumbnail
return $query;
}
How can I sort through the query->posts and rearrange them so the ones that do have featured images show up before those without.
All of the WP_Post objects are found in an array under $query->posts. You can sort the array using usort() based on whatever criteria you want. Keep in mind that this will only sort each page of results as that is what is returned.
add_filter( 'wpv_filter_query_post_process', 'prefix_rearrange_by_thumbnail' );
function prefix_rearrange_by_thumbnail( $query ) {
$posts = $query->posts;
usort( $posts, 'sort_by_thumbnail' );
return $query;
}
// function used to sort the posts array
function sort_by_thumbnail( $a, $b ){
// the the featured image id so we can sort by it
$a_thumb = get_post_meta( $a->ID, '_thumbnail_id', true );
$b_thumb = get_post_meta( $b->ID, '_thumbnail_id', true );
if ( empty( $a_thumb ) && ! empty( $b_thumb ) ) return 1;
if ( ! empty( $a_thumb ) && empty( $b_thumb ) ) return -1;
return 0;
}
To sort all the pages of the results you need to modify the arguments that are passed to WP_Query using the wpv_filter_query filter. There is a meta_key called "_thumbnail_id" set for each post/page that has a featured image, but the issue is that this meta_key is not set at all for posts/pages without a featured image, so if you use it the results will be sorted by the ID of the featured images, but if it is missing they will be omitted. One option is to set another flag based on that meta_key to use in your sort. A one time cleaned would be needed then you could use a hook on save_post
One time SQL (adjust for your db prefix):
INSERT INTO wp_postmeta( post_id, meta_key, meta_value )
SELECT p.ID, '_has_featured_image', IF ( meta_value IS NULL, 0, 1 ) AS _has_featured_image
FROM wp_posts p
LEFT JOIN wp_postmeta m ON p.ID = m.post_id AND meta_key = '_thumbnail_id'
WHERE p.post_status = 'publish'
AND p.post_type IN ('post','page')
Hook on save_post to keep "_has_featured_image" clean going forward:
add_action( 'save_post', 'set_has_featured_image' );
function set_has_featured_image( $post_id ){
$post = get_post( $post_id );
switch ( $post->post_type ){
case 'post': case 'page':
$thumbnail_id = get_post_meta( $post_id, '_thumbnail_id', true );
update_post_meta( $post_id, '_has_featured_image', ! empty( $thumbnail_id ) );
break;
}
}
Now you can filter on the "_has_featured_image" meta_key:
add_filter( 'wpv_filter_query', 'prefix_rearrange_by_thumbnail' );
function prefix_rearrange_by_thumbnail( $args ){
$args['orderby'] = 'meta_value';
$args['meta_key'] = '_has_featured_image';
return $args;
}
I managed to do it in an easier way...
add_filter( 'wpv_filter_query_post_process', 'prefix_rearrange_by_thumbnail', 10, 3 );
function prefix_rearrange_by_thumbnail( $query, $view_settings, $view_id ) {
if ( !empty( $query->posts ) ) {
$sorted_posts_top = array();
$sorted_posts_bottom = array();
$all_posts = $query->posts;
foreach ($all_posts as $post) {
if ( has_post_thumbnail($post->ID) ) {
$sorted_posts_top[] = $post;
}
else {
$sorted_posts_bottom[] = $post;
}
$query->posts = array_merge((array)$sorted_posts_top, (array)$sorted_posts_bottom);
}
}
return $query;
}
However, your answer is still VERY helpful. Thank you SO MUCH for sharing!!!!!!!!!!!!!!!!
I have a template where there is a main latest featured post (tagged as featured), and then 8 more below it.
On the homepage, i was able to query for the latest featured post, and then pass its id to a function in the pre_get_posts wordpress filter. it works great there
function mh_exclude_featured_query( $query ) {
if(is_home()){
if ( $query->is_home() ) {
$feat = get_featured_post();
$query->query_vars['post__not_in'] = array($feat->ID);
}
}
}
add_action( 'pre_get_posts', 'mh_exclude_featured_query' );
but i'm also trying to do the same thing in the category.php, where i would show the latest post tagged as featured from that category. and then the remaining posts below with the featured post excluded.
Unfortnately, when i try the same method as above by using the pre_get_posts filter, i get stuck in an infinite loop and run out of memory.
if($query->is_category() && $query->is_main_query()){
$cur_cat_id = get_cat_id( single_cat_title("",false) );
$feat = get_featured_post($cur_cat_id);
$query->query_vars['post__not_in'] = array($feat->ID);
}
not sure what i'm doing differently that leads to a memory exhaustion. the category.php and index.php are near identical in their structure.
use the pre_get_posts filter:
<?php
function excludePostId($query) {
$postIds = array(
24, 10
);
if (is_category() && is_main_query()) {
set_query_var('post__not_in', $postIds);
}
}
add_action('pre_get_posts', 'excludePostId');
is_category() will accept a category slug or ID. You can limit which categories the post will be excluded from.
Add This Code
<?php if(!is_category('category_id')){
echo 'Your Code Here';
}?>
I have many categories, but for clearity I will do an example with only two:
News that contains many posts
Products that contains many pages (I've added this feature in functions.php)
I want that archive.php displays:
the posts when the user choose the category News
the pages when the user choose the category Products
At the moment Wordpress by deafult shows only posts and not pages.
I know that this is possible by adding a simple function in functions.php but I can't find it.
EDIT: For another project with custom post type "Books" I used this code
function query_post_type($query) {
$post_types = get_post_types();
if ( is_category() || is_tag()) {
$post_type = get_query_var('books');
if ( $post_type ) {
$post_type = $post_type;
} else {
$post_type = $post_types;
}
$query->set( 'post_type', $post_type );
return $query;
}
}
add_filter('pre_get_posts', 'query_post_type');
Is there something like that for my case?
You can query for solely pages in the WP Query.
PHP:
$args = array(
'post_type' => 'page'
);
$query = new WP_Query( $args );
This will return all pages in your database, and zero posts. Vice versa, you could have 'post_type' => 'post' to query all posts, but that's the default behaviour of the WP Query.
For more documentation on this, check out the WP Query reference in the Wordpress Codex.