Support » Developing with WordPress » Ignore and posts per page cancel each other out in get_posts

  • Resolved Beee

    (@beee)


    I have a simple get_posts query (in author.php) which has an include for an array/string of IDs and a posts per page parameter. These 2 don’t seem to work well together here.

    When posts per page and include are set, posts per page is ignored.
    If I remove the included array/string, posts per page ‘starts working’.

    Tested on a vanilla wordpress with twentyfifteen theme.

    This is my entire query:

    $rows = $wpdb->get_results( $wpdb->prepare( "
                SELECT *
                FROM {$wpdb->prefix}postmeta
                WHERE meta_key LIKE %s
                AND meta_value = %s
                ", 'idf_tagged_riders_%_member', // meta_name: $ParentName_$RowNumber_$ChildName
        $user_id
    ) );
    
    if ( $rows ) {
        
        $post_ids  = array();
        $id_string = '';
        // loop through rows and build array of posts to sort them by post_date
        foreach ( $rows as $row ) {
            $post_ids[] = $row->post_id;
        }
        $id_string              = implode( ',', $post_ids );
        $paged                  = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
        $mentioned_args         = array(
            'posts_per_page' => '2',
            'include'        => $id_string,
            'paged'          => $paged,
            'orderby'        => 'date',
            'order'          => 'DESC',
        );
        $context[ 'mentioned' ] = get_posts( $mentioned_args );
    
    }

    When I dump $rows, all expected rows are there.
    Dito for $post_ids and $id_string.

    I built quite a few sites but I’ve never seen this happen before.
    There’s no pre_get_posts action which is active (I checked). The entire file which contains them is commented out.

Viewing 11 replies - 1 through 11 (of 11 total)
  • Moderator bcworkz

    (@bcworkz)

    It may be because the included IDs exceed the posts per page count, as the included IDs are part of the count. The posts per page argument is used directly in the LIMIT clause of the query. I think you need to count the IDs being included and add that to the posts per page argument in order to get 2 additional posts beyond those included.

    If that doesn’t work, you could directly set the LIMIT clause, but doing so breaks pagination, so you’d need to manage pagination yourself. In many cases this is not as bad as it might sound. Also, dynamically varying the posts per page argument will probably break pagination anyway, so it’s possibly something you’d need to manage no matter what.

    The include argument of get_posts() is the shorthand of setting post__in to the given array of posts and posts_per_page to the number of items in post__in.

    See this, from the source of get_posts():

    if ( ! empty($r['include']) ) {
    		$incposts = wp_parse_id_list( $r['include'] );
    		$r['posts_per_page'] = count($incposts);  // only the number of posts included
    		$r['post__in'] = $incposts;
    

    To only get 2 posts from the array given, use post__in instead of include.

    • This reply was modified 2 months, 1 week ago by  Jacob Peattie.
    • This reply was modified 2 months, 1 week ago by  Jacob Peattie.

    Thanks @bcworkz and @jakept.

    Substituting ‘include’ with ‘post__in’ did the trick…. Never knew include and posts per page ‘bit’ each other when used side by side.

    Ah well learn something new every day πŸ™‚

    Solving this puzzle always creates new (related) ones. As mentioned in the first post, this query is run on an author page. So a query is already set for that page (or any subpage with a query var), namely all posts written by the queried user.

    This query almost always returns 0 because only 10 of our 3000 members can write posts. But what I would like to show is the posts in which the user got mentioned (which is the array $post_ids).

    So what I would need to do is to change the query with pre get posts to include all authors who have written posts but leave the $query->author_name intact since that ‘triggers’ the author page (otherwise the author page doesn’t work).

    I have been trying several variations in pre get posts but I can’t seem to make it work.

    Any suggestions ?

    Moderator bcworkz

    (@bcworkz)

    So what you really want is the posts in “posts__in”, regardless of author? The author argument is there because that was the request, but removing it would cause the wrong template to load? Then the thing to do is to go ahead and alter the query as desired, then force the author template to be loaded by adding a hook to “template_include”. Add the hook within the “pre_get_posts” callback only after you’ve verified you’re dealing with an author request.

    Correct…. I want to show the post_ids on an author page (only if a certain query is set).

    The query on which author pages ‘check’ is (afaik) author name. When I change that to false I get an error that the queried object of the author page can’t be found, which would make sense imo.

    I have tried overriding the query with pre get posts but it just won’t work (yet).

    I have never used the hook “template_include”. I’ll look into it…

    Since this hasn’t been working for me, I have been working on an alternative solution which loads a separate get_posts (next to the author query), show that on the sub page, but then pagination doesn’t work, so I created a unique paging function for just this page, that works perfectly but now I need to find a way to ‘fake page 2’, because it isn’t ‘recognised’ yet. Which makes sense because the author has 0 posts and thus there is no page 2.

    Moderator bcworkz

    (@bcworkz)

    Heh, when we try to alter any one item, we find it hitched to everything else in the installation. (Apologies to John Muir) πŸ™‚

    That’s a reasonable approach, despite having to deal with pagination. The only real downside is the original query is run and discarded unused. pre_get_posts and template_include would be an improvement mainly because there is no wasted query.

    I have looked into template_include but i’m not sure if that’s the thing I need/want because we’re not talking about a page but an author archive (or I’m missing the scope of the function).

    I did try the function but then it loses its queried object.

    I think I can achieve what I want if I can fake page 2 of the author archives.

    I have been trying several variations in pre get posts but I can’t seem to make it work<a

    • This reply was modified 1 month, 3 weeks ago by  novinterf.
    • This reply was modified 1 month, 3 weeks ago by  novinterf.
    • This reply was modified 1 month, 3 weeks ago by  novinterf.

    yeah… me neither… sucks….

    Gonna close this topic since the original question is answered. Will rephrase the question in a new topic.

Viewing 11 replies - 1 through 11 (of 11 total)
  • You must be logged in to reply to this topic.