This is strange and should not happen by default. get_posts
uses WP_Query
. If you look at the source code of get_posts
, all the parameters passed to get_posts
is passed unchanged to WP_Query
except parameters like category
which is changed to cat
, the include
and exclude
parameters to include or exclude certain posts which is changed to post__in
and post__not_in
respectively and numberposts
which is changed to posts_per_page
.
1839 function get_posts( $args = null ) {
1840 $defaults = array(
1841 'numberposts' => 5, 'offset' => 0,
1842 'category' => 0, 'orderby' => 'date',
1843 'order' => 'DESC', 'include' => array(),
1844 'exclude' => array(), 'meta_key' => '',
1845 'meta_value' =>'', 'post_type' => 'post',
1846 'suppress_filters' => true
1847 );
1848
1849 $r = wp_parse_args( $args, $defaults );
1850 if ( empty( $r['post_status'] ) )
1851 $r['post_status'] = ( 'attachment' == $r['post_type'] ) ? 'inherit' : 'publish';
1852 if ( ! empty($r['numberposts']) && empty($r['posts_per_page']) )
1853 $r['posts_per_page'] = $r['numberposts'];
1854 if ( ! empty($r['category']) )
1855 $r['cat'] = $r['category'];
1856 if ( ! empty($r['include']) ) {
1857 $incposts = wp_parse_id_list( $r['include'] );
1858 $r['posts_per_page'] = count($incposts); // only the number of posts included
1859 $r['post__in'] = $incposts;
1860 } elseif ( ! empty($r['exclude']) )
1861 $r['post__not_in'] = wp_parse_id_list( $r['exclude'] );
1862
1863 $r['ignore_sticky_posts'] = true;
1864 $r['no_found_rows'] = true;
1865
1866 $get_posts = new WP_Query;
1867 return $get_posts->query($r);
1868
1869 }
The only noticeable differences are the following two lines
1846 'suppress_filters' => true
1864 $r['no_found_rows'] = true;
where line 1846 is the most important. By default, get_posts
are not altered or interfered with by any filters which act on WP_Query
because this is muted by line 1846. WP_Query
by default is altered by any external filter that used on it, this goes for the main query and any custom query using WP_Query
. That is why it is important to use conditionals like is_main_query()
to target the main query specifically.
It is also very very important to know that any poorly written query that is not reset can and will interfere with both WP_Query
and get_posts
and thus the output from them. query_posts
also breaks many functionalities on a page
To debug this, you will need to look for any filters that acts on WP_Query
or the main query, also look out for any instance of pre_get_posts
. Look for any custom query, and make sure that all instances of WP_Query
has been reset with wp_reset_postdata()
. If you have used setup_postdata( $post )
with get_posts
, then you need to reset that as well. Remove any use of query_posts
.
If this does not work, switch to a default theme and test this again. Don’t forget to clear browser and plugin caches first. Lastly, deactivate each plugin one by one and test after each one. This will show you which plugin is causing this if it is plugin related