The default excerpts in WordPress are, in my opinion, a bit crap. All images and subheadings are stripped out and it always stops in the middle of a sentence. It also ends in that “[…]” which I don’t like.
Modifying the Excerpt Code
Thankfully I found a way to improve the excerpt. WordPress has a function to create excerpts for you:
function wp_trim_excerpt($text) { // Fakes an excerpt if needed global $post; if ( '' == $text ) { $text = get_the_content(''); $text = apply_filters('the_content', $text); $text = str_replace('\]\]\>', ']]>', $text); $text = strip_tags($text); $excerpt_length = 55; $words = explode(' ', $text, $excerpt_length + 1); if (count($words)> $excerpt_length) { array_pop($words); array_push($words, '[...]'); $text = implode(' ', $words); } } return $text; }
Unfortunately this is in the WordPress source code itself, so without FTP access you can’t modify it. Even then you shouldn’t as this can seriously mess up your install and screw up future updates.
Thankfully WordPress provides a way to override default behaviour by modifying your Theme’s function.php:
remove_filter('get_the_excerpt', 'wp_trim_excerpt'); add_filter('get_the_excerpt', 'improved_trim_excerpt');
Improving the Text
Starting with code from the article and adding a minor modification to include <h2> tabs I ended up with this:
function improved_trim_excerpt($text) { global $post; if ( '' == $text ) { $text = get_the_content(''); $text = apply_filters('the_content', $text); $text = str_replace('\]\]\>', ']]>', $text); $text = preg_replace('@<script[^>]*?>.*?</script>@si', '', $text); $text = strip_tags($text, '<p><h2>'); $excerpt_length = 80; $words = explode(' ', $text, $excerpt_length + 1); if (count($words)> $excerpt_length) { array_pop($words); array_push($words, '[...]'); $text = implode(' ', $words); } } return $text; }
There are still a few niggling issues here. It still cuts off halfway through a sentence. It still ends with ‘[…]’. The lack of images creates a wall of text on the front page that makes the site unattractive.
To fix the sentence problem I looked up some PHP functions and came up with this:
// Cut off after the last complete sentence. $sentences = explode('.', $text); array_pop($sentences); $text = implode('.', $sentences);
Simply split the excerpt on the period, remove the last sentence and recombine the remaining sentences. Next I needed to replace the ‘[…]’. I removed the line that does this and added this to the end:
// Add a 'Read More...' link. $text = $text.'.</p><p><a href="'.get_permalink().'">Read More...</a></p>';
Note how I add the period and the closing </p>. These were removed along with the last sentence so I add them back here. I also use the get_permalink function to create a link to the article.
Adding a Thumbnail
For images I decided to use the featured image for each article. Adding this to the excerpt turned out to be quite simple:
// Include the thumbnail if there is one. if ( has_post_thumbnail() ) { $text = the_post_thumbnail().$text; }
Of course I check a thumbnail exists before I do this.
Lastly I wanted to allow people to click the images to see the articles, since they draw the eyes:
// Make all thumbnails link to the article. add_filter( 'post_thumbnail_html', 'my_post_image_html', 10, 3 ); function my_post_image_html( $html, $post_id, $post_image_id ) { $html = '<a href="' . get_permalink( $post_id ) . '" title="' . esc_attr( get_the_title( $post_id ) ) . '">' . $html . '</a>'; return $html; }
Now I have excerpts that look quite nice. The best thing is they work on category and search pages as well.
More?
There is one other thing to mention about excerpts. There is a <!--more-->
tag that you can use to manually tell WordPress when to cut off for the excerpt. I’ve noticed that if any images or code examples get included in my excerpts they get messed up. I’ve made it a habit now to always include this tag in my articles before the first image or code example, and this helps keep things neat and tidy.
The Complete Code
The final code for my custom excerpts looks like this:
// Make all thumbnails link to the article. add_filter( 'post_thumbnail_html', 'my_post_image_html', 10, 3 ); function my_post_image_html( $html, $post_id, $post_image_id ) { $html = '<a href="' . get_permalink( $post_id ) . '" title="' . esc_attr( get_the_title( $post_id ) ) . '">' . $html . '</a>'; return $html; } // Set default image size for thumbnails. add_image_size(690, 270, True); add_image_size(640, 180, True); set_post_thumbnail_size(640, 180, True); // Improve the article excerpts. function improved_trim_excerpt($text) { global $post; if ( '' == $text ) { // Get default content. $text = get_the_content(''); $text = apply_filters('the_content', $text); $text = str_replace('\]\]\>', ']]>', $text); // Filter out any scripts. $text = preg_replace('@<script[^>]*?>.*?</script>@si', '', $text); // Strip out HTML but keep subheadings and paragraphs. $text = strip_tags($text, '<p><h2>'); // Increase the length to 80 words. $excerpt_length = 80; $words = explode(' ', $text, $excerpt_length + 1); if (count($words)> $excerpt_length) { array_pop($words); $text = implode(' ', $words); } // Cut off after the last complete sentence. $sentences = explode('.', $text); array_pop($sentences); $text = implode('.', $sentences); // Add a 'Read More...' link. $text = $text.'.</p><p><a href="'.get_permalink().'">Read More...</a></p>'; // Include the thumbnail if there is one. if ( has_post_thumbnail() ) { $text = the_post_thumbnail().$text; } } return $text; } // Replace default excerpt filter with our custom filter. remove_filter('get_the_excerpt', 'wp_trim_excerpt'); add_filter('get_the_excerpt', 'improved_trim_excerpt');