Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I am using get_posts and get_comments to build several loops on the page, at which I am having some issues in pagination.

I have the global posts per page option (Settings > Reading) set to 10, and this seems to vary the problem. As of now, I can easily get to Page 2 - http://dev.ashfame.com/author/ashfame/page/2/, but Page 3 returns a 404.

If I lower the global value, I get to have more paginated pages but not all (lesser number than how many there should be).

Update: I just tried setting my custom setting as 2 (and the global one too), and WordPress should paginate until page 4 (I have 7 items to show) but now it does but also page 5 & 6. 7 gives 404. Why? How do I troubleshoot this thing now?

Progress: @t31os helped me figure out that its the WP default query on the page which is setting up the pagination for that page. Now I can think of one way to kill the default WP query on that page (but how?) and then how would I further paginate the author.php page? Or is there any other way of doing it?

Current code:

<?php

            $author_details = $wp_query->get_queried_object();

            // Posts Per Page option
            // $ppp = get_option('posts_per_page');
            $ppp = 1; //custom setting, if you want to obey the global setting here, comment this line and uncomment the above line

            if (!is_paged()) {
                $custom_offset = 0;
            } else {
                $custom_offset = $ppp*($paged-1);
            }

            echo '<h1>Author ID : '.$author_details->ID.', Page : '.$paged.', Custom Offset : '.$custom_offset.'</h1>';

            ?>

            <h2>Articles</h2>

            <?php
            $args = array(
            'numberposts' => $ppp,
            'offset' => $custom_offset,
            'category' => 7,
            'author' => $author_details->ID
            );

            $posts_data = get_posts( $args );

            // print_r($posts_data);

            if ( count( $posts_data ) > 0 ) {               
                echo '<ul>';                
                foreach ( $posts_data as $post ) {                      
                    echo '<li><a href="'.get_permalink( $post->ID ).'">'.$post->post_title.'</a></li>';
                }               
                echo '</ul>';
            } else {
                echo '<p>No articles by this user</p>';
            }           
            ?>

            <h2>Journals</h2>

            <?php
            $args = array(
            'numberposts' => $ppp,
            'offset' => $custom_offset,
            'category' => 6,
            'author' => $author_details->ID
            );
            $posts_data = get_posts( $args );

            // print_r($posts_data);

            if ( count( $posts_data ) > 0 ) {               
                echo '<ul>';                
                foreach ( $posts_data as $post ) {                      
                    echo '<li><a href="'.get_permalink( $post->ID ).'">'.$post->post_title.'</a></li>';
                }               
                echo '</ul>';
            } else {
                echo '<p>No journals by this user</p>';
            }
            ?>

            <h2>Questions</h2>

            <?php
            $args = array(
            'numberposts' => $ppp,
            'offset' => $custom_offset,
            'category' => 3, // parent category ID is enough
            'author' => $author_details->ID
            );
            $posts_data = get_posts( $args );

            // print_r($posts_data);

            if ( count( $posts_data ) > 0 ) {               
                echo '<ul>';                
                foreach ( $posts_data as $post ) {                      
                    $category_array = get_the_category( $post->ID );
                    $category_name = $category_array[0]->name;
                    $category_permalink = get_category_link( $category_array[0]->term_id );
                    echo '<li><a href="'.get_permalink( $post->ID ).'">'.$post->post_title.'</a>
                    <br />In: <a href="'.$category_permalink.'">'.$category_name.'</a><br />'.get_comments_number( $post->ID ).' Answers</li>';
                }               
                echo '</ul>';
            } else {
                echo '<p>No questions by this user</p>';
            }
            ?>

            <h2>Answers</h2>

            <?php
            $args = array(
            'user_id' => $author_details->ID,
            'number' => $ppp,
            'offset' => $custom_offset,
            'status' => 'approve'
            );
            $answers_list = get_comments( $args );

            // print_r($answers_list);

            if ( count( $answers_list ) > 0 ) {
                $date_format = get_option( 'date_format' );
                echo '<ul>';
                foreach ( $answers_list as $answer ) {
                    echo '<li>Answer: '.substr( $answer->comment_content, 0, 20 ).'..<br />'.date( $date_format, strtotime( $answer->comment_date ) ).'<br />Question: <a href="'.get_permalink( $answer->comment_post_ID ).'">'.get_the_title( $answer->comment_post_ID ).'</a></li>';
                }
                echo '</ul>';
            } else {
                echo '<p>No answers by this user</p>';
            }
            ?>
share|improve this question
    
where is the code that prints out the pagination?, also what are you tring to paginate articles? jurnals? questions? answer? all of them? and as far as i can see is that you should use wp_reset_postdata(); after each foreach loop. –  Bainternet Apr 12 '11 at 22:07
    
@Bainternet I am not printing out pagination links as of now, just modifying the address bar directly. Is there an easy way? Also, I am not using setup_postdata(), I am directly iterating on the result of get_posts(). Yes, I am paginating all of them. Please take a look at a single section of the code, others are similar. –  Ashfame Apr 12 '11 at 22:43
    
Set posts_per_page to your desired value, keep doing what you're doing with the offset, but explicitly set paged to 1.. and see if things then behave correctly.. –  t31os Apr 12 '11 at 22:44
    
@t31os where should I set paged exactly? –  Ashfame Apr 12 '11 at 22:47
    
Inside your $args array along with the other values. :) –  t31os Apr 12 '11 at 22:52
show 8 more comments

1 Answer 1

up vote 2 down vote accepted

t31os says: [See edit history for previous code and comments]

Using Ajax to paginate your queries

I've put together some code that will fetch your posts and comments via ajax using simple prev/next navigation via ajax.

1) Replace all the code you posted in your author.php with the following..

<?php $cat_settings = array( 'Articles' => 7, 'Journals' => 6, 'Questions' => 3 ); ?>
<?php do_action( 'author_ajax_catposts', $cat_settings ); ?>

2) Create a Javascript file in your theme's directory called authorposts.js and place the following code into that file.

jQuery(document).ready( function($) {

    if( 'undefined' == typeof( aacVars ) )
        return;

    $('.aacnav').click(function() {

        var r = $( $(this).attr('href') );
        var a = $( $(this).attr('href') + '-ap' );
        var c = this.className.split(' ');

        if( 
            'undefined' == typeof( c ) || 
            'undefined' == typeof( r ) || 
            'undefined' == typeof( a ) 
        )
            return false;

        var d = { 
            action:      aacVars.posts_action, 
            _ajax_nonce: aacVars.nonce,
            author:      aacVars.author,
            category:    $(this).attr('href')
        };

        p = parseInt( a.text() );
        c = c.pop();

        switch( c ) {
            case 'aacnext':
                if( r.children('p.nomore').length )
                    return false;
                d.page = p + 1;
            break;
            case 'aacprev':
                if( p < 2 )
                    return false;
                d.page = p - 1;
            break;
            default:
                return false;
        }

        $.post( aacVars.ajaxpth, d, function( res ) {
            if( '-1' == res ) {
                alert( 'auth failed' );
                return false;
            }
            $( r ).html( res );
            $( a ).text( d.page );
        });

        return false;
    });

    $('.aacnavc').click(function() {

        var r = $( '#aac-comments' );
        var n = $( '#aac-comments-ap' );
        var l = $(this).attr('href');

        if( 
            'undefined' == typeof( n ) || 
            'undefined' == typeof( r ) 
        )
            return false;

        var d = { 
            action:      aacVars.comments_action, 
            _ajax_nonce: aacVars.nonce,
            author:      aacVars.author
        };

        p = parseInt( n.text() );

        switch( l ) {
            case '#next':
                if( r.children('p.nomore').length )
                    return false;
                d.page = p + 1;
            break;
            case '#prev':
                if( p < 2 )
                    return false;
                d.page = p - 1;
            break;
            default:
                return false;
        }

        $.post( aacVars.ajaxpth, d, function( res ) {
            if( '-1' == res ) {
                alert( 'auth failed' );
                return false;
            }
            r.html( res );
            $( n ).text( d.page );
        });

    });

});

3) Copy the following code into your theme's functions.php file.

class Author_Ajax_Cats {

    private $posts_per_page    = 3;
    private $comments_per_page = 1;
    private $posts_action      = 'aac-posts';
    private $comments_action   = 'aac-comments';
    private $js                = array();

    public function __construct() {

        add_action( 'parse_request',                            array( $this, 'aac_parse_request' ) );
        add_action( 'wp_ajax_nopriv_' . $this->posts_action,    array( $this, 'aac_ajax_posts' ) );
        add_action( 'wp_ajax_' .        $this->posts_action,    array( $this, 'aac_ajax_posts' ) );
        add_action( 'wp_ajax_nopriv_' . $this->comments_action, array( $this, 'aac_ajax_comments' ) );
        add_action( 'wp_ajax_' .        $this->comments_action, array( $this, 'aac_ajax_comments' ) );
        add_action( 'wp_enqueue_scripts',                       array( $this, 'aac_enqueue_scripts' ) );
        add_action( 'author_ajax_catposts',                     array( $this, 'aac_print_posts' ) );
    }
    public function aac_parse_request( $wp ) {

        if( !isset( $wp->query_vars['author_name'] ) || is_admin() )
            return;

        $wp->query_vars['paged'] = 1;

    }
    private function setup_js_vars() {

        global $wp_query;

        $this->js['author']          = $wp_query->get_queried_object_id();
        $this->js['posts_action']    = $this->posts_action;
        $this->js['comments_action'] = $this->comments_action;
        $this->js['nonce']           = wp_create_nonce( 'noncekey' );
        $this->js['ajaxpth']         = admin_url( 'admin-ajax.php' );
    }
    public function aac_enqueue_scripts() {

        if( !is_author() )
            return;

        $this->setup_js_vars();

        wp_register_script( 'author-ajax', get_bloginfo('stylesheet_directory') . '/authorposts.js', array( 'jquery' ), time(), true );
        wp_localize_script( 'author-ajax', 'aacVars', $this->js );
        wp_enqueue_script( 'author-ajax' );
    }
    public function aac_ajax_comments() {

        if( !isset( $_POST['page'] ) || !isset( $_POST['author'] ) )
            die;

        check_ajax_referer( 'noncekey' );

        $authID = absint( $_POST['author'] );
        $paged  = absint( $_POST['page'] );

        $args = array(
            'user_id' => $authID,
            'number'  => $this->comments_per_page,
            'offset'  => ( ( $paged - 1 ) * $this->comments_per_page ),
            'status'  => 'approve',
            'type'    => 'comment'
        );

        $answers_list = get_comments( $args );
        if( empty( $answers_list ) ) {
            printf( '<p class="nomore">%s</p>', __( 'No more answers by this user.' ) );
            die;
        }
        $_comment_walk = new Walker_Comment;

        echo '<ul>';
        $_comment_walk->paged_walk( $answers_list, 0, 1, $this->comments_per_page, array( 
            'style' => 'ul', 
            'avatar_size' => 15, 
            'max_depth' => 1, 
            'callback' => array( $this, 'author_comment_walker' ) 
        ) );
        echo '</ul>';

        die;
    }
    public function aac_ajax_posts() {

        if( !isset( $_POST['page'] ) || !isset( $_POST['category'] ) || !isset( $_POST['author'] ) )
            die;

        check_ajax_referer( 'noncekey' );

        $catID  = absint( str_replace( '#aac-', '', $_POST['category'] ) );
        $authID = absint( $_POST['author'] );
        $paged  = absint( $_POST['page'] );

        $args = array(
            'paged'       => $paged,
            'numberposts' => $this->posts_per_page,
            'author'      => $authID,
            'cat'         => $catID
        );
        $posts = get_posts( $args );

        if( empty( $posts ) )
            die( sprintf( '<p class="nomore">%s</p>', __( 'No more posts.' ) ) );

        $this->do_posts( $posts );

        die;
    }
    public function aac_print_posts( $cats = array() ) {

        //get_the_term_list( $post->ID, 'category', '<ul><li>', '</li><li>', '</li></ul>' )

        foreach( $cats as $heading => $id ) {
            $args = array( 
                'cat'         => $id,
                'paged'       => 1, // Always the first page on load
                'numberposts' => $this->posts_per_page, 
                'author'      => $this->js['author']
            );
            $posts = get_posts( $args );

            printf( '<h2>%s</h2>', $heading );

            if( empty( $posts ) ) {
                printf( '<div><p class="nomore">%s</p></div>', __( 'No posts.' ) );
                continue;
            }

            printf( '<div id="aac-%d" class="aac-result">', $id );

            $this->do_posts( $posts );

            printf( '</div><div>' );
            printf( '<p class="alignright">Page: <span id="aac-%1$d-ap">1</span></p><p class="alignleft"><a class="aacnav aacprev" href="#aac-%1$d">%2$s</a> <a class="aacnav aacnext" href="#aac-%1$d">%3$s</a></p>', $id, __('Previous'), __('Next') );
            printf( '<br class="clear" /></div>' );
        }
        ?>

        <h2>Answers</h2>

        <?php
        $args = array(
            'user_id' => $this->js['author'],
            'number'  => $this->comments_per_page,
            'status'  => 'approve',
            'type'    => 'comment'
        );
        $answers_list = get_comments( $args );
        if( empty( $answers_list ) ){
            printf( '<p>%s</p>', __( 'No answers by this user' ) );
            return;
        }
        $_comment_walk = new Walker_Comment;

        printf( '<div id="aac-comments"><ul>' );

        $_comment_walk->paged_walk( $answers_list, 0, 1, $this->comments_per_page, array( 
            'style' => 'ul', 
            'avatar_size' => 15, 
            'max_depth' => 1, 
            'callback' => array( $this, 'author_comment_walker' ) 
        ) );

        printf( '</ul></div><div><p class="alignright">Page: <span id="aac-comments-ap">1</span></p><p class="alignleft"><a class="aacnavc" href="#prev">%s</a> <a class="aacnavc" href="#next">%s</a></p><br class="clear" /></div>', __('Prev'), __('Next') );
    }
    private function do_posts( $posts, $term_id = 0 ) {

        echo '<ul>';
        foreach( $posts as $post )
            printf( '<li><a href="%s">%s</a></li>', get_permalink( $post->ID ), get_the_title( $post->ID ) );
        echo '</ul>';

    }
    public function author_comment_walker( $comment, $args, $depth ) {

        $GLOBALS['comment'] = $comment; 
        ?>

        <li>
            <div id="comment-<?php comment_ID(); ?>">
                <div>
                    <?php echo get_avatar( $comment, $args['avatar_size'], $default = '<path_to_url>' ); ?> <?php echo get_comment_author_link(); ?> answered 
                    <a href="<?php echo get_permalink( $comment->comment_post_ID ); ?>"><?php echo get_the_title( $comment->comment_post_ID ); ?></a> on <a href="<?php echo htmlspecialchars( get_comment_link( $comment->comment_ID ) ) ?>"><?php printf( __( '%1$s at %2$s' ), get_comment_date(),  get_comment_time() ); ?></a>
                    <?php //edit_comment_link( __( '(Edit)' ),'  ','' ); ?>
                </div>
                <?php // comment_text() ?>
                <p><?php comment_excerpt(); ?></p>
            </div>
        <?php
    }
}
$aac = new Author_Ajax_Cats;

4) Fire up an author page and see how the results look and to check my code works for you.

How it looks locally with test data.

Click to view larger version, scaled down for the answer

Live demo of the code in action:** (test site)

http://t31os.onatha.com/author/t31os/

5) Provide some feedback.. :)

I hope that helps...

share|improve this answer
    
Till the point we are not killing any kitten by hacking any core file, it works for me ;) This works great, the way I want. Any chance can I set empty pages to 404, just need to know the place (GLOBALS only perhaps?), if possible. I can access any page right now :) –  Ashfame Apr 13 '11 at 19:11
    
ok never mind that, I checked some code & its going to be some more complicated with additional queries. But do you have any suggestions for how I generate paginated links? I mean with the current code, I can't know if there is anything left further so that I should create a link to the next page or not. Thoughts? –  Ashfame Apr 13 '11 at 19:55
    
Have you considered just using Ajax to fetch the posts and using prev / next links for each ajaxified set of posts? The ajax response could return a "No more posts" message quite easily.. (and would avoid the need for lookup queries to count the posts an author has in a particular category). –  t31os Apr 14 '11 at 21:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.