Wright This Way

Custom WordPress excerpt

On a blog index page, WordPress will automatically show a small excerpt of the content, which by default is a total of 55 words. It doesn’t try to complete a sentence and excerpt to the next period, or even the end of the paragraph. It just cuts off in mid sentence. There are ways to change the built in function for a greater number of words, but it will still cut off when that limit is reached.

There are a number of examples online for a custom function that will excerpt the first paragraph of an entry, which is definitely a bit more useful, but in testing that out vs some of my older posts from the old site, I found that on occasion I’d have a very brief first paragraph before diving into my topic, and would in some cases need a second paragraph to really give a decent excerpt.

After playing around with some different options and looking at my old blog, I decided that I needed to set both a minimum number of paragraphs, and a minimum word count, and needed to make my excerpt large enough to satisfy both of these values.

For my theme, my index.php file calls another file named content.php, which displays the individual blog entries. In that file, the following is my excerpt code:

	$content = apply_filters('the_content', get_the_content());
	$showMore = true;

	// Get the desired # of paragraphs, if less than the desired # of
	// words then get another paragraph.
	$theParagraphs = get_theme_mod( 'excerpt_paragraphs', 1 );
	$paragraphCount = substr_count($content, '</p>');

	if ($paragraphCount > $theParagraphs) {
		// If there are more paragraphs than we want excerpted
		$theLength = strposN($content, "</p>", $theParagraphs);
		$theExcerpt = substr($content,0,$theLength);

		while (str_word_count($theExcerpt) < get_theme_mod( 'excerpt_words', 60 )) {
			theExcerpt = substr($content,0,(strposN($content, "</p>", ++$theParagraphs)) + 4);

			if ($theParagraphs >= $paragraphCount) {
				$showMore = false;
				break;
			}
		}
	} else {
		// too few paragraphs to excerpt, show all content
		$showMore = false;
		$theExcerpt = $content;
	}

	// Close off any tags that were left hanging in the excerpt
	$theExcerpt = force_balance_tags($theExcerpt);
	echo $theExcerpt;

Some explanation of the above. My theme has two control settings for the word count (excerpt_words) and paragraph count (excerpt_paragraphs). The above code will fetch those values and use them to create a suitable excerpt. The first part of the code fetches the entire post, then does a count of the total number of paragraphs based on the </p> tag that gets appended to each paragraph. If there are too few paragraphs, then we just output the whole post as the excerpt.

Inside that IF statement, I first set $theExcerpt to the number of desired paragraphs. I then use a WHILE statement to check the word length, if it’s too low then I add more paragraphs until that limit is reached, or until we’ve reached the end of the post.

I also set a flag for $showMore so that if there is more to read, we can later display a ‘Continue Reading…’ link to the full article.

At the very end, I use the force_balance_tags function. This is a very handy built in WordPress function that will, as the name implies, close off any tags that were left open. Paragraph tags, block quotes, div, etc. I found that if I didn’t do this, then my Read More text was ending up in odd locations because of tags being left open. I had started doing some sanity check coding to try to handle this all on my own before I discovered this function that did it all for me.



Leave a Reply

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