How can I change the length of the_excerpt() in Wordpress without editing core files?
Well, first we need to figure out exactly where the excerpt text is truncated. Checking wp-includes/default-filters.php, around line 128 we see:
add_filter('get_the_excerpt', 'wp_trim_excerpt');
Ok, so that’s how it’s cut off. The first step in our fix is to prevent the default function from running and truncating the text at the default length. The easiest way to do this? Simply remove the filter by adding a line to your theme’s functions.php file:
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
Great. So now we’ve got the_excerpt() looking exactly like the_content(). Now we need to create our own pretty little function to handle truncating the_excerpt to the length we need. Since those crazy Wordpress devs have already thought of everything, we’ll use their original function as a template for our new one. The original function can be found in wp-includes/formatting.php, around line 779:
[php]
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;
}
[/php]
See the line $excerpt_length = 55;? That’s the one we want to change!
Take your new wp_trim_excerpt function and stick it in your theme’s functions.php file. Be sure to rename it to something unique. You should end up with something similar to this:
[php]
function custom_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 = 75;
$words = explode(’ ‘, $text, $excerpt_length + 1);
if (count($words) > $excerpt_length) {
array_pop($words);
array_push($words, ‘[...]‘);
$text = implode(’ ‘, $words);
}
}
return $text;
}
[/php]
Note that I only made two changes: 1) renamed the function to “custom_trim_excerpt”, and 2) changed the excerpt_length to 75.
Great, we’re almost there! One step left. Now we have to tell Wordpress to use our new custom function to truncate the_excerpt. We’ll do this by adding a new filter, similar to the one we removed at the very beginning. Stick this line in your theme’s functions.php file:
add_filter('get_the_excerpt', 'custom_trim_excerpt');
Be sure to substitute your new function’s name, assuming you didn’t use the same one I did, and you should be all set!
Note: This guide was written using Wordpress 2.2. The exact procedure may vary with versions, but should be fairly similar.
Nice guide, thanks!
Excellent post. I am wondering though, how do you remove the P tag?
Garry: All the <p> tags in WordPress are handled by another of the default filters:
add_filter('comment_text', 'wpautop', 30);
In order to remove that tag, you’ll need to drop another line in your functions.php file:
remove_filter('comment_text', 'wpautop');
But be forewarned - that’ll remove absolutely all of your auto-paragraph formatting. You’ll need to handle all that yourself.
Is there a way to make an exception? Meaning, I only need one instance where I need the P tag removed. Can something be written that will remove it only the one spot I need it?
Looking back, I realize that I wasn’t paying enough attention when I wrote that earlier comment. Obviously a lack of caffeine if I’ve ever seen one. That should be:
remove_filter('the_excerpt', 'wpautop');
I just saw the first wpautop and snagged it, not bothering to look and see that it was for comment text, not post text… Doh!
Anyway…
Can something be written? I’m sure it can… Would it be feasible to do so? That depends…
Only thing I can envision:
You add your own hook for the_excerpt that runs with a high priority (like first, 0:
add_filter('the_excerpt', 'custom_excerpt_no_autop', 0);).In that function, essentially, you want to check and see if this post has a custom field you set on that individual post. If that custom field has the value you set (whatever you wanted to use to indicate not to auto-p this post), you run your
remove_filter('the_excerpt', 'wpautop');and the post is left alone.In actual practice, I’m not sure how well this would work out, or how it would affect any excerpts coming after this post. You may actually need to hook again with very low priority and re-add the default wpautop rule.
I’d probably try to find another way… Like fixing the actual issue: that auto-p’ing is causing that big of a problem.
Can I create another instruction that give a special set of instruction for the excerpt where I want to use it uniquely just once without the P tag?
Sort of like in CSS you can tell H1 to be really big but only when it is found in the header, and then you can tell H1 to be smaller in the content or post sections.
So can something be written like this:
If the php excerpt code is found here then remove the P tag; however, if the php excerpt code is found everywhere else keep the P tag.
The only other option I see would be a modification of what I suggested earlier. You basically substitute the portion where you check to see if there’s a custom field with your skip value with the part where you check to see what the other contents of the post are… Either way, the rest of the brutal hack remains…
Works like a charm. Thanks for sharing!
Glad I could help, Nic!
complete code for wp 2.3 / template functions.php
// Excerptfunktion aus p-includes/default-filters.php ausser Kraft setzen
remove_filter(’get_the_excerpt’, ‘wp_trim_excerpt’);
// Neue Excerptfunktion aktivieren
add_filter(’get_the_excerpt’, ‘modifiziert_wp_trim_excerpt’);
// Excerpt kürzen
function modifiziert_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 = 45;
$words = explode(’ ‘, $text, $excerpt_length + 1);
if (count($words) > $excerpt_length) {
array_pop($words);
array_push($words, ‘…’);
$text = implode(’ ‘, $words);
}
}
return $text;
}
Maybe I’m just being a dumb web designer but can’t you just change the value on the original function instead of creating a new one? I’ve just done it now - changed the default value of 55 to 40 and it’s worked a treat.
Thanks anyway, I would have been lost without this article!
Nathan: Changing core files that come with packaged distributions is generally considered bad practice, since you then have to remember to make those same changes every time you upgrade (or you randomly lose the custom functionality when you forget).
Since this function doesn’t have a plugin filter specifically for the length of the_excerpt(), you have to reimplement the whole function and substitute your new one in using the plugin hook that is available.
Hi!
I running WP 2.6.1 and I simply cant get the code to work. Adding the remove_filter and add_filter is fine but when adding the function I wind up with a blank page…
Any ideas? Thanks!
remove_filter(’get_the_excerpt’, ‘wp_trim_excerpt’);
add_filter(’get_the_excerpt’, ‘custom_trim_excerpt’);
function custom_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 = 25;
$words = explode(’ ‘, $text, $excerpt_length + 1);
if (count($words) > $excerpt_length) {
array_pop($words);
array_push($words, ‘[...]‘);
$text = implode(’ ‘, $words);
}
}
return $text;
}