It's actually somehow simple and I add this answer because the suggested duplicate does not match your needs (but it does give some pointers).
What you want is to cut a string a maximum length but preserve the last word. So you need to find out the position where to cut the string (and if it's actually necessary to cut it at all).
As getting the length (strlen
) and cutting a string (substr
) is not your problem (you already make use of it), the problem to solve is how to obtain the position of the last word that is within the limit.
This involves to analyze the string and find out about the offsets of each word. String processing can be done with regular expressions. While writing this, it reminds me on some actually more similar question where this has been already solved:
It does exactly this: Obtaining the "full words" string by using a regular expression. The only difference is, that it removes the last word (instead of extending it). As you want to extend the last word instead, this needs a different regular expression pattern.
In a regular expression \b
matches a word-boundary. That is before or after a word. You now want to pick at least $length
characters until the next word boundary.
As this could contain spaces before the next word, you might want to trim the result to remove these spaces at the end.
You could extend your function like the following then with the regular expression pattern (preg_replace
) and the trim
:
/**
* Cut a string at length while preserving the last word.
*
* @param string $str
* @param int $length
* @param string $suffix (optional)
*/
function trim_word($str, $length, $suffix = '...')
{
$len = strlen($str);
if ($len < $length) return $str;
$pattern = sprintf('/^(.{%d,}?)\b.*$/', $length);
$str = preg_replace($pattern, '$1', $str);
$str = trim($str);
$str .= $suffix;
return $str;
}
Usage:
$str = 'How are you today?';
echo trim_word($str, 10); # How are you...
You can further on extend this by reducing the minimum length in the pattern by the length of the suffix (as it's somehow suggested in your question, however the results you gave in your question did not match with your code).
I hope this is helpful. Also please use the search function on this site, it's not perfect but many gems are hidden in existing questions for alternative approaches.