Truncating string to whole words

I have written php for ages so i’m really rusty.

What i want to do is truncate a string using words not characters but i also don’t want it cut off in mid sentence. I want it truncated at a period.

I found a couple of functions that either truncate using words or truncate to a period but not both.

This function (I found on here) truncates to a period

function abbr($str, $maxLen) {
     if (strlen($str) > $maxLen && $maxLen > 1) {
         preg_match("#^.{1,".$maxLen."}\\.#s", $str, $matches);
         return $matches[0];
     } else {
         return $str;

whereas this function truncates to whole words

function trunc($phrase, $max_words)
   $phrase_array = explode(' ',$phrase);
   if(count($phrase_array) > $max_words && $max_words > 0)
      $phrase = implode(' ',array_slice($phrase_array, 0, $max_words)).'...'  
   return $phrase;

I would like to combine them both so i have a complete sentence.

I also found another useful function that does both but the problem with this one is that i strips out the breaks so where i would start a new paragraph, it joins it up to make a new sentence, I don’t know if anyone can modify that!

//This function intelligently trims a body of text to a certain
//number of words, but will not break a sentence.
function smart_trim($string, $truncation) {
    $matches = preg_split("/\\s+/", $string);
    $count = count($matches);

    if($count > $truncation) {
        //Grab the last word; we need to determine if
        //it is the end of the sentence or not
        $last_word = strip_tags($matches[$truncation-1]);
        $lw_count = strlen($last_word);

        //The last word in our truncation has a sentence ender
        if($last_word[$lw_count-1] == "." || $last_word[$lw_count-1] == "?" || $last_word[$lw_count-1] == "!") {
            for($i=$truncation;$i<$count;$i++) {

        //The last word in our truncation doesn't have a sentence ender, find the next one
        } else {
            //Check each word following the last word until
            //we determine a sentence's ending
            for($i=($truncation);$i<$count;$i++) {
                if($ending_found != TRUE) {
                    $len = strlen(strip_tags($matches[$i]));
                    if($matches[$i][$len-1] == "." || $matches[$i][$len-1] == "?" || $matches[$i][$len-1] == "!") {
                        //Test to see if the next word starts with a capital
                        if($matches[$i+1][0] == strtoupper($matches[$i+1][0])) {
                            $ending_found = TRUE;
                } else {

        //Check to make sure we still have a closing <p> tag at the end
        $body = implode(' ', $matches);
        if(substr($body, -4) != "</p>") {
            $body = $body."</p>";

        return $body; 
    } else {
        return $string;
$brutus  = "There is a tide in the affairs of men. 
Which, taken at the flood, leads on to fortune;
Omitted, all the voyage of their life
Is bound in shallows and in miseries.
On such a full sea are we now afloat,
And we must take the current when it serves,
Or lose our ventures.";

$sentences = explode(".", $brutus);

echo $sentences[0] . '.' . $sentences[1] .'.';

There is a tide in the affairs of men. Which, taken at the flood, leads on to fortune; Omitted, all the voyage of their life Is bound in shallows and in miseries.

If you want X characters, then to find the previous . before that - substr($string, 0, 500); then from that point, search back for the next previous . strrpos($string, ‘.’);

Howver, thats making the assumption there are .'s to go at.

$sentences = explode(".", substr($brutus, 500));

I get this error now

Notice: Undefined offset: 1 in C:\Apache\htdocs\ est1.php on line 12

which is on line

echo $sentences[0] . '.' . $sentences[1] .'.';

$sentences = explode(".", substr($brutus, 0, 500));  

Sorry chap, [fphp]substr[/fphp] requires the string, the start, the end. I forgot the start.

To make that code more useful (I was just trying to point out the use of [fphp]explode[/fphp]) you could make a function which loops through the sentences rather than having to take the chance there actually is more than one sentence in the string.

Thanks for your help…works nicely.

Quick question tho…is it possible to keep the line breaks? Sometimes there may be one sentence, a new paragraph and more sentences.