How To List All Posts Of An Archive, A Category Or A Search Result

In: web resources

8 Jul 2010

Archive pages are usually paged according to your settings in options/reading. Sometimes you may want to offer a page with all posts for an archive (time, category, search result).

You need:

  • a separate address for the unpaged archive,
  • a filter for the internal WordPress query and
  • a link to your ‘all posts’ page.

We put everything into a class to avoid name collisions and to keep the global namespace clean.
We name the file class.View_All_Posts.php.

Let’s start with the class, the parameter and a checker, this is easy:

class View_All_Posts
{
    /**
     * GET parameter to trigger a complete, not paged archive.
     * @var string
     */
    protected $all_param = 'all';

    /**
     * Are we there already?
     *
     * @return bool
     */
    public function is_all_posts()
    {
        return isset ( $_GET[$this->all_param] );
    }
}

For the address I use a very simple approach: a GET parameter named all. You may change the name here; just stay with ASCII chars from a—z. все_сообщения will get you in trouble!

Next we need a constructor that manages our work:

    public function __construct()
    {
        /* Register the query argument. */
        add_filter('query_vars', array ( $this, 'add_query_arg') );

        /* Hook into the query. */
        add_action('pre_get_posts', array ( $this, 'view_all_posts') );
    }

The constructor references two internal functions – add_query_arg() and view_all_posts(), which we build next:

    /**
     * Registers the query arg in WordPress.
     * Otherwise it will be unset.
     *
     * @param  array $vars Already registered query args.
     * @return array
     */
    public function add_query_arg( array $vars )
    {
        return array_merge( $vars, array ( $this->query_arg ) );
    }

    /**
     * Alters the query to remove the paging.
     * @return void
     */
    public function view_all_posts()
    {
        if ( ! $this->is_all_posts() )
        {
            return;
        }

        $GLOBALS['wp_query']->query_vars['nopaging'] = TRUE;

        return;
    }

The first function just registers our GET parameter in WordPress. The second alters the query to the database and removes the paging.

We are almost done. A template tag for the link would be nice, wouldn’t it?

    /**
     * Creates the markup for the link.
     *
     * Usage in archive.php, category.php or search.php:
     * $GLOBALS['view_all_posts']->get_allposts_link();
     *
     * @param  string $text Linktext
     * @param  bool   $print echo or return
     * @return string|void
     */
    public function get_allposts_link(
        $text   = 'View all posts'
    ,   $before = '<p class="allpostslink">'
    ,   $after  = '</p>;'
    ,   $print  = TRUE
    )
    {
        if ( $this->is_all_posts()
         or $GLOBALS['wp_query']->found_posts <= get_option('posts_per_page')
        )
        {   // No link needed.
            return;
        }

        if ( isset ( $_SERVER['QUERY_STRING'] )
            && ! empty ( $_SERVER['QUERY_STRING'] )
        )
        {
            /* We have already visible GET parameters: /?hello=world. */
            $new_url = $_SERVER['REQUEST_URI'] . '&amp;';
        }
        else
        {
            /* Note the difference: REQUEST_URL doesn't include
             * the query string while REQUEST_URI does. */
            $new_url = $_SERVER['REQUEST_URL'] . '?';
        }

        $link = "$before<a href='$new_url$this->all_param'>$text</a>$after";

        if ( $print )
        {
            print $link;
            return;
        }
        return $link;
    }

Note: $GLOBALS['wp_query']->found_posts holds the sum of all posts for a given query, not just for the current page. Useful if you want to print out the total number on a paged archive.

If you want to avoid duplicate content, hide the full archives from search engines in your header:

    /**
     * Prevents indexing from search engines.
     *
     * Add this as an action to 'wp_head'.
     *
     * @return void
     */
    public function meta_noindex()
    {
        if ( $this->is_all_posts() )
        {
             print '<meta name="robots" content="noindex">';
        }
    }

Our class is complete. Now we put an object of the class into the global namespace …

$GLOBALS['view_all_posts'] = new View_All_Posts;

… add an action to wp_head

add_action(
    'wp_head'
,   array ( $GLOBALS['view_all_posts'], 'meta_noindex' )
);

… and include the file into the functions.php of our theme:

require_once dirname(__FILE__) . DIRECTORY_SEPARATOR
    . 'class.View_All_Posts.php';

In our archive templates (archive.php, category.php, search.php) we print the link:

$GLOBALS['view_all_posts']->get_allposts_link();

Done.

Oh, wait … maybe you want to see the full code? And a download link?

Here’s the link: Download class.View_All_Posts.php

The complete code:

/**
 * Adds a view all posts page to any query.
 * @author Thomas Scholz http://toscho.de
 * @version 1.1
 */
class View_All_Posts
{
    /**
     * GET parameter to trigger a complete, not paged archive.
     * @var string
     */
    protected $all_param = 'all';

    public function __construct()
    {
        /* Register the query argument. */
        add_filter('query_vars', array ( $this, 'add_query_arg') );

        /* Hook into the query. */
        add_action('pre_get_posts', array ( $this, 'view_all_posts') );
    }

    /**
     * Registers the query arg in WordPress.
     * Otherwise it will be unset.
     *
     * @param  array $vars Already registered query args.
     * @return array
     */
    public function add_query_arg( array $vars )
    {
        return array_merge( $vars, array ( $this->query_arg ) );
    }

    /**
     * Alters the query to remove the paging.
     * @return void
     */
    public function view_all_posts()
    {
        if ( ! $this->is_all_posts() )
        {
            return;
        }

        $GLOBALS['wp_query']->query_vars['nopaging'] = TRUE;

        return;
    }

    /**
     * Are we there already?
     *
     * @return bool
     */
    public function is_all_posts()
    {
        return isset ( $_GET[$this->all_param] );
    }

    /**
     * Creates the markup for the link.
     *
     * Usage in archive.php, category.php or search.php:
     * $GLOBALS['view_all_posts']->get_allposts_link();
     *
     * @param  string $text Linktext
     * @param  bool   $print echo or return
     * @return string|void
     */
    public function get_allposts_link(
        $text   = 'View all posts'
    ,   $before = '<p class="allpostslink">'
    ,   $after  = '</p>'
    ,   $print  = TRUE
    )
    {
        if ( $this->is_all_posts()
        or $GLOBALS['wp_query']->found_posts <= get_option('posts_per_page')
        )
        {   // No link needed.
            return;
        }

        if ( isset ( $_SERVER['QUERY_STRING'] )
            && ! empty ( $_SERVER['QUERY_STRING'] )
        )
        {
            /* We have already visible GET parameters: /?hello=world. */
            $new_url = $_SERVER['REQUEST_URI'] . '&amp;';
        }
        else
        {
            /* Note the difference: REQUEST_URL doesn't include
             * the query string while REQUEST_URI does. */
            $new_url = $_SERVER['REQUEST_URL'] . '?';
        }

         $link = "$before<a href='$new_url$this->all_param'>$text</a>$after";

        if ( $print )
        {
            print $link;
            return;
        }
        return $link;
    }
}

$GLOBALS['view_all_posts'] = new View_All_Posts;

Go to Source

3 Responses to How To List All Posts Of An Archive, A Category Or A Search Result

Avatar

yidlmama

July 12th, 2010 at 4:31 am

A sales void is a transaction that is cancelled before it is ever finalized.
A return is a refund…when someone returns an item they have already purchased for either cash or another item.

Avatar

Adam L

August 10th, 2010 at 6:35 am

While its not always necessarily it's probably a good practice to do it. It ensures that the function is finished and the control of the program returns back to after the function call. Functionally you can get away without them but mark the end of the function. I don't think its fair to lose points for something like that however since that seems like more of a "style" choice than the only "right" way to program.

Avatar

beth z

September 6th, 2010 at 3:47 am

this game called adventure quest worlds is in beta and is online with other players, the downside, is at this time there is only sound effects and no music, you can only use set typed out messages to communicate with other players if you are not a member(has a monthly fee). The graphics I really like as they remind me of a old school mmorpg I used to play.From what I seen you can change your hair , eye color , and skin color as much and as often as you want. Lots of neat pets and items to collect. Here is link if you want to check it out:

http://www.aqworlds.com/

Comment Form

About this blog

This blog delivers stylish and dynamic news for designers and web-developers on all subjects of design, ranging from: CSS, Ajax, Javascript, web design, graphics, typography, advertising & much more. Our goal is to help you communicate effectively on the web with an engaging website or functional interface.