Lesson 6. Displaying a list of posts on a page and pagination

Lesson 6. Displaying a list of posts on a page and pagination

Today’s article concludes the series of lessons on developing an autocomplete plugin. Due to the plugin's functionality expansion, many changes have been made. So we’ll need to go through the code from the very beginning again, but without too many details. In short, two additional shortcodes have been added for more flexible output manipulation. One shortcode displays the list of posts, the other — the pagination.

A small side note: using Git in your projects greatly simplifies your life. It requires almost no time investment, and certainly no money (hello Bitbucket and GitLab). When reviewing the code, it’s easy to see what was changed and where.

Now, let’s get to work

We add two variables to the class properties:

private $QueryPosts;
private $posts_per_page = 10;

What does this give us?
$QueryPosts will be used in two other shortcodes (pagination and output), so we place the WP_Query object in a class property.
$posts_per_page stores the number of posts per page. Sure, we could hardcode this number in multiple places, but… it’s much better to manage it in one place. For example, if we later want to extend our base “[post-autocomplete-form]” shortcode with a “posts_per_page” parameter — like “[post-autocomplete-form posts_per_page=10]”.

And in the constructor, we add two new shortcodes:

add_shortcode('post-autocomplete-posts', array($this, 'shortcode_post_autocomplete_posts'));
add_shortcode('post-autocomplete-pagination', array($this, 'shortcode_post_autocomplete_pagination'));

Form shortcode

The “[post-autocomplete-form]” shortcode is handled by the method:

public function shortcode_post_autocomplete_form()
{
	global $post;

	$content = '';
	if(is_a($post, 'WP_Post'))
	{
		$content .= '<form action="' . get_permalink($post -> ID) . '" class="post-autocomplete-form" method="GET">';
		$content .= '<input type="text" name="text" class="post-autocomplete__field" placeholder="Enter search text" value="'.filter_input(INPUT_GET, 'text', FILTER_SANITIZE_STRING).'">';
		$content .= '</form>';
	}

	return $content;
}

We added an action attribute to the form, pointing to the current page. Also, we check the global $post variable to avoid errors.

Shortcode for displaying found posts

I called it “[post-autocomplete-posts]” and it’s handled by the following method:

public function shortcode_post_autocomplete_posts()
{
	//Sets
	$content = '';
	$page = max(1, get_query_var('paged'));
	$text_search = filter_input(INPUT_GET, 'text', FILTER_SANITIZE_STRING);
	$offset = $this -> posts_per_page * ($page - 1);

	if(empty($text_search))
	{
		return '';
	}

	$this -> QueryPosts = new WP_Query();
	$Posts = $this -> QueryPosts -> query([
		'posts_per_page' => $this -> posts_per_page,
		'offset' => $offset,
		's' => $text_search,
		'orderby' => 'title',
		'order' => 'ASC',
	]);

	if($this -> QueryPosts -> have_posts())
	{
		$content .= '<div>Posts found: '.$this -> QueryPosts -> found_posts.'</div>';
		$content .= '<ul class="post-autocomplete-posts">';
		foreach($Posts as $Post)
		{
			$content .= '<li>';
			$content .= '<a href="'.get_permalink($Post -> ID).'">';
			$content .= esc_attr($Post -> post_title);
			$content .= '</a>';
			$content .= '</li>';
		}
		$content .= '</ul>';
	}
	else
	{
		$content .= '<div class="post-autocomplete-nofound">';
		$content .= 'Nothing found';
		$content .= '</div>';

		return $content;
	}
	wp_reset_postdata();


	return $content;
}

Let’s look at part of the code in detail:

$page = max(1, get_query_var('paged'));
$text_search = filter_input(INPUT_GET, 'text', FILTER_SANITIZE_STRING);
$offset = $this -> posts_per_page * ($page - 1);

1. On the first pagination page, WP returns 0, for the second — 2, third — 3, etc. To handle this, we use max().
2. We retrieve the GET data.
3. We calculate the offset for pagination.

A DB query using the WP_Query core object:

$this -> QueryPosts = new WP_Query();
$Posts = $this -> QueryPosts -> query([
	'posts_per_page' => $this -> posts_per_page,
	'offset' => $offset,
	's' => $text_search,
	'orderby' => 'title',
	'order' => 'ASC',
]);

We sort the results alphabetically by title.

I generally prefer using get_posts as a wrapper over WP_Query — shorter syntax, same arguments. But here, we need the total number of posts (for pagination), so we use WP_Query directly.
Further in the code, we check if posts were found — if so, we output the list. If not — we show a "Nothing found" message.

Shortcode for pagination

To display pagination, place the shortcode “[post-autocomplete-pagination]” at the end of the page or post.
Its code lives in the “shortcode_post_autocomplete_pagination()” method:

//Sets
$content = '';

if(!empty($this -> QueryPosts))
{
	$big = 999999999;
	$result = paginate_links([
		'base' => str_replace($big, '%#%', get_pagenum_link($big)),
		'format' => '',
		'current' => max(1, get_query_var('paged')),
		'total' => ceil($this -> QueryPosts -> found_posts / $this -> posts_per_page)
	]);

	$content .= str_replace('/page/1/', '', $result);
}

return $content;

As you can see, we check if $this->QueryPosts exists. If yes — we build pagination using the built-in WordPress paginate_links() function.

We define all parameters ourselves to avoid relying on the global $wp_query — since we’re using our own custom query.

Testing the post autocomplete plugin

Via the WordPress admin, create a page and insert the following code:

[post-autocomplete-form']

It has long been known that people get distracted by readable content when assessing design and layout. That’s why Lorem Ipsum is used — it provides a fairly standard filler and real character distribution in paragraphs.

[post-autocomplete-posts]

[post-autocomplete-pagination]

Save it and preview the result. Enter some text — the autocomplete works. If there are results in the DB, click on one — the page reloads and shows the matching post.
Now test further — type something like “a” or “o”, hit enter — and if there are more than 10 posts, pagination should appear. If pagination also works on the last page and doesn’t disappear — congratulations, the plugin works and you’ve created a simple solution using three shortcodes.

That’s it. You can find the full plugin code in the repo at this link. Thanks for reading and see you soon!

List of all lessons in the series

Posts on similar topics

Are you having problems with your WordPress site? Do you need additional functionality? A custom plugin or a new page?
Then write to me via the feedback form, and I will try to help you.

Write a comment

Your email address will not be published. Required fields are marked *