Hacking WordPress – how to show all comments with a custom quicktag

One of the blessings in WordPress is the vast array of plugins available. However, it is also one of the curses….because it makes us lazy. While this doesn’t seem to be problematic in the short term, in the longer term, large numbers of plugins can cause blogs to slow down, and even worse, the various plugins could start interfering with each other. So, whenever I can, I like to write my own code – the two advantages are that
1 – I can control exactly what goes in to the code, making it do what I need and no more
2 – I’ve written the code so if things start to clash, it’s going to be easier to debug.

So, let’s learn how to create a WordPress page to display every comment on our blog and just for fun, let’s also code up a quicktag which we can place into any page or post where we want the comments displayed.

Start in your theme’s functions.php

add_filter('the_content', 'all_your_comments_are_belong_to_me');

function all_your_comments_are_belong_to_me($content) {
	if (strstr($content, '<!--all_your_comments-->')) { 
	  $allcomments = get_comments();

    $strout = "<ul>";

		foreach ($allcomments as $comment) {
			$postforcomment = get_post($comment->comment_post_ID); 
			$strout .= '<li><strong><a href="'. $comment->comment_author_url . '">' . $comment->comment_author . '</a> had a thought about <a href="'.get_permalink($comment->comment_post_ID).'">'.$postforcomment->post_title.'</a></strong>';
			$strout .= ' on <small>' . $comment->comment_date . '</small><br>';
			$strout .= '<p>' . $comment->comment_content . '</p></li>';

		$strout .= '</ul>';

		$content = str_replace('<!--all_your_comments-->', $strout, $content);

	return $content;

What’s all this code doing? Well first, we set up a filter with the add_filter command. Filters allow us to extend much of the core WordPress functionality, allowing us to add our own processing. This is very powerful because it means we can modify the way WordPress saves or displays our data without having to delve into the core WordPress code and hack our WordPress install to pieces. That in turn means that we can safely update the core of our blog without having to worry about re-applying any customised functions that we have written for our blog. Filters are what makes plugins work like magic.

So for this bit of magic, we are adding a filter to a hook called the_content. This tells WordPress that we want to execute some of our own code whenever WordPress is creating the content of a page or post just before it is displayed on the screen. The function we are going to call is all_your_comments_are_belong_to_me which we define right after the add_filter command.

This function takes one argument by default – $content (or whatever you want to call it) which is the actual written content of your post or page (for example you are reading the content of my post right now). We wrap everything in an if statement – which means that we will only process the rest of our code in our function if somewhere in our content we have the following quicktag: all_your_comments.

Okay, into the meat and potatoes – getting every comment to display. Here we use a tasty function called get_comments() which, as the name suggests, gets all the comments for every post in our blog. There are various arguments you can supply to this WordPress function, but we really don’t need any of them for the purposes of our demo. Now we loop through all the comments, creating a string that is the actual html of all the comments we want to output. At the same time, to add a little extra value we grab the post associated with each comment. This is a little bit more costly in terms of actual database round trips, but what the heck, we want a nice output.

We create our string (format it however you want and define your styles in your css. And then, the pièce de résistance – the str_replace which says: “take this lovely html string I have created and substitute it into our $content variable wherever you find the phrase <!––all_your_comments––>”. Remember $content is the actual written content of our page. Finally, we return our $content variable from our function.

One gotcha – when using a hook into the_content, you must return something, so at the very least, if we fail our if condition we just send back the $content that we got in. If you don’t, WordPress will display nothing – no content for your post. Be warned.

Okay now all that’s left is to write a new page to display all these comments – whip up a lovely new page or post and write it up as you wish. At any point, slap in the all_your_comments quicktag and save.

This code is both good and bad. Good in that it is quick to code up but bad in that every time WordPress displays a post or page, it will go through our function – this will slow down our blog (but hey, I’m taking one for the team on the demo page). So how else could we do this? Well we could create a template page which would do this for us – this would be more efficient, but less flexible because we wouldn’t be able to control where the comments were injected into the contents of the page.

So, I hope you got something out of that. This can easily be extended into a plugin if you are feeling that way inclined; perhaps I’ll do that at some point in the future. For now though, hopefully you enjoyed that little step into WordPress hacking and have a better understanding of how easy it is to code up a custom quicktag in WordPress to pull in all of the comments in your blog.