Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

How do I trim the_excerpt to a certain character count? WordPress

  • SOLVED

How do I apply a filter to the_excerpt so that I can return 200 characters? The word count isn't quite cutting it for exact sentence lengths.

I'd also like to keep this filter if possible:


function devinsays_excerpt_more($more) {
return '... // <a href="' . get_permalink() . '" class="read-more">Read More</a>';
}
add_filter('excerpt_more', 'devinsays_excerpt_more');


My experiments haven't quite worked:



remove_filter( 'get_the_excerpt', 'wp_trim_excerpt' );
add_filter( 'get_the_excerpt', 'devinsays_trim_excerpt' );

function devinsays_trim_excerpt( $content ) {
return substr( 0, 200, strip_tags( $content ) );
}


Probably missing something small. Thanks for the help.

Note: Not looking for word count. Character count should include white space.

Answers (16)

2010-08-06

Utkarsh Kukreti answers:

Should be

return substr( strip_tags( $content ), 0, 200 );


Devin Price comments:

Hm, already tried that.

I'm seeing that it perhaps trims the excerpts that are manually entered- but it doesn't automatically trim the_content down if no excerpt is manually entered. Normally the_except will return something even if there is no manual excerpt in.


Utkarsh Kukreti comments:

Try hooking into the_excerpt then?


remove_filter( 'get_the_excerpt', 'wp_trim_excerpt' );

add_filter( 'the_excerpt', 'devinsays_trim_excerpt' );


function devinsays_trim_excerpt( $content ) {

return substr( strip_tags( $content ), 0, 200 );

}


Devin Price comments:

This is cutting it- for sure. But the character lengths coming out are:

186 char
188 char
197 char
188 char

If I change the substr to 210 the char count goes up on all items by 10. So, that is working. But not sure why it doesn't return the full characters of substr.

Also, on posts with less than 200 characters (like the standard Hello World! WordPress post)- nothing gets outputted.


Utkarsh Kukreti comments:

Try using

add_filter( 'the_excerpt', 'devinsays_trim_excerpt', 11 );

2010-08-06

enodekciw answers:

Paste this into functions.php

<?php
function short_excerpt($string) {
echo substr($string, 0, 200);
}
?>


And then, edit your theme and replace

<?php the_excerpt(); ?>

with this one:
<?php short_excerpt(get_the_excerpt()); ?>


Devin Price comments:

Seems like that would cut off my read more filter- but will try. That can always be appended instead.


enodekciw comments:

Modified a bit. This goes into functions.php:
<?php
function short_excerpt($string, $id) {
$excerpt = substr(strip_tags($string), 0, 200);
$read-more = '<a href="' . get_permalink($id) . '" class="read-more">Read More</a>';
echo $excerpt . ' ' . $read-more;
}
?>

Replace

<?php the_excerpt(); ?>

with this:

<?php short_excerpt(get_the_excerpt(), get_the_ID()); ?>


enodekciw comments:

Ok it seems like $read-more variable breaks the code. Change that code in functions.php to this one:
<?php
function short_excerpt($string, $id) {
$excerpt = substr(strip_tags($string), 0, 200);
$more = '<a href="' . get_permalink($id) . '" class="read-more">Read More</a>';
echo $excerpt . ' ' . $more;
}
?>


Usage:
<?php short_excerpt(get_the_excerpt(), get_the_ID()); ?>

Tested it on my own blog - works fine.


enodekciw comments:

btw, this also includes whitespaces into your 200 characters count ;)

2010-08-06

Chris Lee answers:


function devinsays_trim_excerpt( $content ) {
$limit = 200;
$content = $excerpt;
$excerpt = explode(' ', get_the_excerpt(), $limit);
if (count($excerpt)>=$limit) {
array_pop($excerpt);
$excerpt = implode(" ",$excerpt).'...';
} else {
$excerpt = implode(" ",$excerpt);
}
$excerpt = preg_replace('`\[[^\]]*\]`','',$excerpt);
return $excerpt;

}

remove_filter( 'get_the_excerpt', 'wp_trim_excerpt' );
add_filter( 'get_the_excerpt', 'devinsays_trim_excerpt' );


Devin Price comments:

Breaks the site. Shows only the first item, with no except.

2010-08-06

Sidd answers:

Hey Devin,

Give this a try. Add the following code to the functions.php This filter is used by wp_trim_excerpt()


function new_excerpt_length($length) {
return 200;
}
add_filter('excerpt_length', 'new_excerpt_length');



-- SOME CODE OMITTED --


Devin Price comments:

That returns a word count.

2010-08-06

Michael Fields answers:

add_filter( 'excerpt_length', 'mytheme_filter_excerpt_length' );
if( !function_exists( 'mytheme_filter_excerpt_length' ) ) {
function mytheme_filter_excerpt_length( $length ) {
return 20;
}
}


Devin Price comments:

Returns a word count.


Michael Fields comments:

Might need some fine tuning, but I think this is what you are looking for?

add_filter( 'the_excerpt', 'razorback_filter_excerpt', 1 );
add_filter( 'the_content', 'razorback_filter_excerpt', 1 );
function razorback_filter_excerpt( $content ) {
if( !is_single() && !is_page() ) {
$c = wp_kses( $content, array() );
$c = substr( $c, 0, 200 );
if( !empty( $c ) ) {
return '<p>' . $c . '</p>';
}
return $c;
}
return $content;
}


Devin Price comments:

Semi works. Very similar outputs to what I'm getting with Utkarsh. Where excerpts where words get cut off, it's generally 199 char. But not always.


Michael Fields comments:

My last idea would be to swap mb_substr() for substr().

2010-08-06

West Coast Design Co. answers:

Hey Devin,

Checkout

<strong>Content and Excerpt Word Limit</strong>
[[LINK href="http://wcdco.info/au"]]http://wcdco.info/au[[/LINK]]

then add ‘<?php content('25'); ?>. ‘
REPLACE (25) WITH THE AMOUNT OF CHARICTORS YOU WISH TO SHOW.


Cheers!


Devin Price comments:

Looking for a character limit.

2010-08-06

Lee Rickler answers:

Try this:

Instead of:
<?php the_excerpt(); ?>

Use:
<?php $len = 200; $newExcerpt = substr($post->post_excerpt, 0, $len);
if(strlen($newExcerpt) < strlen($post->post_excerpt)) { $newExcerpt = $newExcerpt." ...";
} echo "".$newExcerpt.""; ?>


Devin Price comments:

If someone hasn't manually entered an excerpt- it returns nothing. Also, would prefer to have a filter which also keep the readmore filter intact.

2010-08-06

Roberto Mas answers:

This always worked for me and yes it counts white space also. you can create multiple exceprts this way

in functions.php add

//custom excerpt
function new_excerpt_length($length) {
return 100;
}
function cutMe($content){
$limit = 350;
$content = strip_tags($content);
if (strlen($content) > $limit)
$content = substr($content, 0, strpos($content," ",$limit)) . ' [...]';
return $content;
}
function cutMeAgain($content){
$limit = 250;
$content = strip_tags($content);
if (strlen($content) > $limit)
$content = substr($content, 0, strpos($content," ",$limit)) . ' [...]';
return $content;
}
function cutMeSmaller($content){
$limit = 100;
$content = strip_tags($content);
if (strlen($content) > $limit)
$content = substr($content, 0, strpos($content," ",$limit)) . ' [...]';
return $content;
}
add_filter('excerpt_length', 'new_excerpt_length');


then in you php code where you want a custum excerpt <?php echo cutMe(get_the_excerpt()); ?>


Devin Price comments:

Seems like it should work, but is giving different lengths. White space counted?

2010-08-06

Lew Ayotte answers:

Sid's answer is the best, in my opinion :)

From: [[LINK href="http://codex.wordpress.org/Function_Reference/the_excerpt#Control_Excerpt_Length_using_Filters"]]http://codex.wordpress.org/Function_Reference/the_excerpt#Control_Excerpt_Length_using_Filters[[/LINK]]

Lew


Devin Price comments:

Returns a word count.


Lew Ayotte comments:

Ah, misread your question ;)...

Try:

function new_wp_trim_excerpt($text) {
return substr($text, 0, 200);
}
add_filter('wp_trim_excerpt', 'new_wp_trim_excerpt');


I haven't tested it yet...


Lew Ayotte comments:

Oh this might be better:

remove_filter( 'get_the_excerpt', 'wp_trim_excerpt' );
add_filter('get_the_excerpt', 'new_wp_trim_excerpt' );

function new_wp_trim_excerpt($text) {
$raw_excerpt = $text;
if ( '' == $text ) {
$text = get_the_content('');

$text = strip_shortcodes( $text );

$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]&gt;', $text);
$text = strip_tags($text);
$text = substr($text, 0, 200)
$excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
$text = $text . $excerpt_more;
}
}


Lew Ayotte comments:

forgot the return :)

function new_wp_trim_excerpt($text) {
$raw_excerpt = $text;
if ( '' == $text ) {
$text = get_the_content('');

$text = strip_shortcodes( $text );

$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]&gt;', $text);
$text = strip_tags($text);
$text = substr($text, 0, 200)
$excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
$text = $text . $excerpt_more;
}

return $text;
}

2010-08-06

Gianni D'Alerta answers:

function.php
function excerpt($num) {
$limit = $num+1;
$excerpt = explode(' ', get_the_excerpt(), $limit);
array_pop($excerpt);
$excerpt = implode(" ",$excerpt)."...";
echo $excerpt;
}


then call this:
<?php excerpt(16); ?>
in the loop, the number represents character count.

I know its not what you wanted as a replacement for the_excerpt() but this has worked in the past for us. Good luck on the answer.

2010-08-07

Guillermo Sornoza answers:

Hi, why don't you try this plugin http://wordpress.org/extend/plugins/advanced-excerpt/ ?

It has been useful for me...

2010-08-07

wjm answers:

This question got my attention because of how many reponses it has received so far.

Your approach is wrong for a simple reason,
you are removing the filter 'wp_trim_excerpt' and are replacing it by a subtr function,

wp_trim_excerpt() basically takes care of empty excerpts and does a lot of (de)formating to the content text to create the new excerpt.

what you need to do is recreate the same features of wp_trim_excerpt but to suit your needs.
Right now there is no way to configure the excerpts by char lenght.
Here is the solution that takes care of that,
at first i used substr, but there is an issue with that. You may cut off words. and wordpress never does that with excerpts so i had do deal with that.

So this function checks the lenght, if it can be cut at 200 char lenght, it will leave all the words. but if longer, it will remove the last word.. maybe leaving the excerpt with 190 something chars (depending on the lenght of the last word) but never longer than 200.

you can change the 200 value by using the new filter called "excerpt_chars_length"

remove_filter( 'get_the_excerpt', 'wp_trim_excerpt' );
add_filter( 'get_the_excerpt', 'devinsays_wp_trim_excerpt' );
function devinsays_wp_trim_excerpt($text) {
$raw_excerpt = $text;
if ( '' == $text ) {
$text = get_the_content('');
$text = strip_shortcodes( $text );
$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]&gt;', $text);
$text = trim(strip_tags($text));

$excerpt_char_length = apply_filters('excerpt_chars_length', 200);
$excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');

if ( strlen($text) > $excerpt_char_length ) {
//We don't want to cut-off words so we need to split the text by words and check its length
$words = preg_split("/[\n\r\t ]+/", $text, -1, PREG_SPLIT_NO_EMPTY);
$count = 0;
foreach ( $words as $k => $word ) {
$count += strlen($word);
//if we have the exact amount of chars, then we leave all the words
if ( $count == $excerpt_char_length ) {
$words = array_slice( $words, 0, $k+1 );
break;
}
//if we have more than the chars required, we don't include the last word
elseif ( $count >= $excerpt_char_length ) {
$words = array_slice( $words, 0, $k ); //skip this last word
break;
}
$count++; // counter increase for additional space
}
$text = implode(' ', $words) . $excerpt_more;
}
}
return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
}


I may submit this to [[LINK href="http://trac.worpress.org"]]trac.worpress.org [[/LINK]] as an enhancement to wp_trim_excerpt() to include words or chars.

full code is here.
[[LINK href="http://wordpress.pastebin.com/kGcJFSbc"]]http://wordpress.pastebin.com/kGcJFSbc[[/LINK]]

Let me know what you think,
if it works, if this is what you excepected
so i can submit the patches to trac.wordpress.org
-wjm


Devin Price comments:

I'm not sure if you had a chance to test this. I'm using 2010 just for the test environment. I removed the regular excerpt filters- and just pasted your code into the functions.php.

The call that's being used in <?php the_excerpt(); ?> from the loop.php.

With your code in, the "read more" filters don't get added- and I'm still getting excerpt character lengths of 238 char, 310 char, etc.

I think this is perhaps the right direction though- not sure why the code is not taking.

I'm going to go back through the other responses again and test various methods.


wjm comments:

Devin

add this code to functions.php
http://wordpress.pastebin.com/kGcJFSbc

in fact, that code was developed under twenty ten.
i dont know why it is not working,
acutally, i removed the readme more filter 2010 added, but your own filter overwrites it.
you may have other code (maybe the from the other responses) interfering with my code.
imho, that is the right way of doing it.

2010-08-07

Valentinas Bakaitis answers:

Really simple way to do this would be to take strip_tags(the_content()); and put it in one of functions mentioned here: http://www.the-art-of-web.com/php/truncate/. It would probably not be the very "right" method to do that, but at least it would be very clear and easy, should be something like 5 lines of code.

2010-08-07

Mirza Rahman answers:

Add this function:
// Excerpt Word Limit
function excerpt($num) {
$link = get_permalink();
$ending = get_option('wl_excerpt_ending');
$limit = $num+1;
$excerpt = explode(' ', get_the_excerpt(), $limit);
array_pop($excerpt);
$excerpt = implode(" ",$excerpt).$ending;
echo $excerpt;
$readmore = get_option('wl_readmore_link');
if($readmore!="") {
$readmore = '<p class="readmore"><a href="'.$link.'">'.$readmore.'</a></p>';
echo $readmore;
}
}


And then call the excerpt (limited to the number of words you need) by using.
<?php excerpt('word-limit'); ?>

2010-08-09

jedw answers:

I recently implemented a function to limit post titles and excerpts to a certain amount of characters. This implementation takes the use of html entities into account. I think you are missing this. From your question I couldn't derive if you want to allow cutting off words at the end of the string, and wether you want to allow special characters (& and other punctuation characters) at the end of the string. Therefore you can set two booleans at the beginning of the function. You can strip it down if you like ofcourse.

Try the following for your situation. This includes the read more link:



remove_filter('the_excerpt', 'wp_trim_excerpt'); // remove default wp filter
add_filter('the_excerpt', 'devinsays_trim_excerpt'); // add custom filter
function devinsays_trim_excerpt($content) {
$max_chars = 200;
$allow_cutoff = true;
$allow_specialchars = true;

$content = strip_tags($content);
$content = html_entity_decode($content, ENT_COMPAT, 'UTF-8'); // decode html entities to characters with (charset UTF-8)
if(strlen($content) > $max_chars) {
$content = substr($content, 0, $max_chars);
if(!$allow_cutoff) {
$last_space = strrpos($content, ' '); // find the last space in string to avoid word cut-off
$content = substr($content, 0, $last_space);
}
trim($content); // trim in case last char is a space;
if(!$allow_specialchars) {
while(eregi('[[:punct:]]$', $content))
$content = trim(eregi_replace('[[:punct:]]$', '', $content)); // strip last char if punctuation
}
}
$more_string = '... // <a href="' . get_permalink() . '" class="read-more">Read More</a>'; // the "read more" link
return $content.$more_string;
}


2010-08-09

Eugen R. answers:

Try to put this into functions.php, and commenting out all other filters for the_excerpt you might have there.

<?php

function trim_excerpt($excerpt) {
return substr($excerpt, 0, 200);
}

add_filter('the_excerpt', 'trim_excerpt');

?>