How can I truncate a string after 20 words in PHP?
-
1You might find [`s($str)->words(20)`](https://github.com/delight-im/PHP-Str/blob/8fd0c608d5496d43adaa899642c1cce047e076dc/src/Str.php#L363) helpful, as found in [this standalone library](https://github.com/delight-im/PHP-Str). – caw Jul 27 '16 at 00:42
29 Answers
function limit_text($text, $limit) {
if (str_word_count($text, 0) > $limit) {
$words = str_word_count($text, 2);
$pos = array_keys($words);
$text = substr($text, 0, $pos[$limit]) . '...';
}
return $text;
}
echo limit_text('Hello here is a long sentence that will be truncated by the', 5);
Outputs:
Hello here is a long ...
-
6This function confuses character count and word count when using $limit in one case as a word selector of the array $pos and in another by determining if the string is long enough. – Aaron Jul 06 '10 at 19:21
-
In the example provided, passing in a value of 5 ensures that the function will act on any word of length greater than 5 characters, so had the test case been "Hello here", the function fails and returns only "..." – Aaron Jul 06 '10 at 19:42
-
-
2`str_word_count` instead of `strlen` should do the trick :) so replace `strlen($text)` with `str_word_count($text,0)` – Val Feb 21 '12 at 15:26
-
1Note on str_word_count($text, 2) from the docs `For the purpose of this function, 'word' is defined as a locale dependent string containing alphabetic characters, which also may contain, but not start with "'" and "-" characters.` you can specify additional characters in the third param, or just use `preg_split('/[\s]+/' $text);` to split by white space. – Chris Hanson Sep 23 '13 at 21:19
-
1its working for english, not for Arabic language, i assume not for UTF-8? or am i missing something? – Omar N Shamali Jun 26 '18 at 14:43
-
Change the number 3
to the number 20
below to get the first 20 words, or pass it as parameter. The following demonstrates how to get the first 3 words: (so change the 3
to 20
to change the default value):
function first3words($s, $limit=3) {
return preg_replace('/((\w+\W*){'.($limit-1).'}(\w+))(.*)/', '${1}', $s);
}
var_dump(first3words("hello yes, world wah ha ha")); # => "hello yes, world"
var_dump(first3words("hello yes,world wah ha ha")); # => "hello yes,world"
var_dump(first3words("hello yes world wah ha ha")); # => "hello yes world"
var_dump(first3words("hello yes world")); # => "hello yes world"
var_dump(first3words("hello yes world.")); # => "hello yes world"
var_dump(first3words("hello yes")); # => "hello yes"
var_dump(first3words("hello")); # => "hello"
var_dump(first3words("a")); # => "a"
var_dump(first3words("")); # => ""

- 15,791
- 4
- 36
- 68

- 146,324
- 131
- 460
- 740
-
2Amazing this is fastest way so far for word limiting, this performs slighty better than explode, great job, well done. – VeeeneX Jul 01 '15 at 04:58
-
2Just a side note: If theres line breaks inside your string, this function will truncade every 20 words for every sentence (assuming you have a line break after every sentence). – Apr 10 '19 at 00:21
-
To match across lines ```((\w+[\W|\s]*){'.($limit-1).'}\w+|\W|\s)(?:(.*|\s))``` will need trim after for the trailing line breaks – Richard Muvirimi Nov 01 '21 at 12:25
To Nearest Space
Truncates to nearest preceding space of target character. Demo
$str
The string to be truncated$chars
The amount of characters to be stripped, can be overridden by$to_space
$to_space
boolean
for whether or not to truncate from space near$chars
limit
Function
function truncateString($str, $chars, $to_space, $replacement="...") {
if($chars > strlen($str)) return $str;
$str = substr($str, 0, $chars);
$space_pos = strrpos($str, " ");
if($to_space && $space_pos >= 0)
$str = substr($str, 0, strrpos($str, " "));
return($str . $replacement);
}
Sample
<?php
$str = "this is a string that is just some text for you to test with";
print(truncateString($str, 20, false) . "\n");
print(truncateString($str, 22, false) . "\n");
print(truncateString($str, 24, true) . "\n");
print(truncateString($str, 26, true, " :)") . "\n");
print(truncateString($str, 28, true, "--") . "\n");
?>
Output
this is a string tha...
this is a string that ...
this is a string that...
this is a string that is :)
this is a string that is--

- 31,583
- 39
- 180
- 284
use explode() .
Example from the docs.
// Example 1
$pizza = "piece1 piece2 piece3 piece4 piece5 piece6";
$pieces = explode(" ", $pizza);
echo $pieces[0]; // piece1
echo $pieces[1]; // piece2
note that explode has a limit function. So you could do something like
$message = implode(" ", explode(" ", $long_message, 20));

- 27,253
- 7
- 76
- 97
-
2Explode's limit function does not act as suggested in this context. See http://www.php.net/manual/en/function.explode.php Example #2, positive limit. – Aaron Jul 06 '10 at 19:48
-
3@Tegeril is correct. Though this would fix it: `$words = implode(" ", array_slice( explode(" ", $t), 0, $count) );` – Dominik Feb 01 '14 at 00:02
-
1@Dominik, You nailed it. This worked immediately, its simple, very understandable and efficient. Thanks to you and to Tegeril for the first part. – Samuel Ramzan Apr 03 '19 at 19:01
Simple and fully equiped truncate() method:
function truncate($string, $width, $etc = ' ..')
{
$wrapped = explode('$trun$', wordwrap($string, $width, '$trun$', false), 2);
return $wrapped[0] . (isset($wrapped[1]) ? $etc : '');
}

- 71
- 1
- 2
Try regex.
You need something that would match 20 words (or 20 word boundaries).
So (my regex is terrible so correct me if this isn't accurate):
/(\w+\b){20}/
And here are some examples of regex in php.

- 73,079
- 34
- 148
- 203
If you code on Laravel just use Illuminate\Support\Str
here is example
Str::words($category->publication->title, env('WORDS_COUNT_HOME'), '...')
Hope this was helpful.

- 764
- 1
- 7
- 16
Its not my own creation, its a modification of previous posts. credits goes to karim79.
function limit_text($text, $limit) {
$strings = $text;
if (strlen($text) > $limit) {
$words = str_word_count($text, 2);
$pos = array_keys($words);
if(sizeof($pos) >$limit)
{
$text = substr($text, 0, $pos[$limit]) . '...';
}
return $text;
}
return $text;
}
With triple dots:
function limitWords($text, $limit) {
$word_arr = explode(" ", $text);
if (count($word_arr) > $limit) {
$words = implode(" ", array_slice($word_arr , 0, $limit) ) . ' ...';
return $words;
}
return $text;
}

- 923
- 1
- 7
- 13
Split the string (into an array) by <
space>
, and then take the first 20 elements of that array.

- 16,092
- 19
- 77
- 136
-
-
won't work if there are punctuations but with no space after them, such as "hello,world". – nonopolarity Jun 08 '09 at 14:58
-
2@Jian Lin That's a problem with the user entering poor data, not the script. – ceejayoz Jun 08 '09 at 14:59
-
1
-
-
-
-
-
Try below code,
$text = implode(' ', array_slice(explode(' ', $text), 0, 32))
echo $text;

- 5,941
- 2
- 44
- 55

- 31
- 3
This worked me for UNICODE (UTF8) sentences too:
function myUTF8truncate($string, $width){
if (mb_str_word_count($string) > $width) {
$string= preg_replace('/((\w+\W*|| [\p{L}]+\W*){'.($width-1).'}(\w+))(.*)/', '${1}', $string);
}
return $string;
}

- 53,146
- 19
- 236
- 237
based on 動靜能量's answer:
function truncate_words($string,$words=20) {
return preg_replace('/((\w+\W*){'.($words-1).'}(\w+))(.*)/', '${1}', $string);
}
or
function truncate_words_with_ellipsis($string,$words=20,$ellipsis=' ...') {
$new = preg_replace('/((\w+\W*){'.($words-1).'}(\w+))(.*)/', '${1}', $string);
if($new != $string){
return $new.$ellipsis;
}else{
return $string;
}
}

- 53,018
- 53
- 161
- 198
Something like this could probably do the trick:
<?php
$words = implode(' ', array_slice(split($input, ' ', 21), 0, 20));

- 23,749
- 20
- 68
- 89
Another solution :)
$aContent = explode(' ', $cContent);
$cContent = '';
$nCount = count($aContent);
for($nI = 0; ($nI < 20 && $nI < $nCount); $nI++) {
$cContent .= $aContent[$nI] . ' ';
}
trim($cContent, ' ');
echo '<p>' . $cContent . '</p>';

- 105
- 1
- 4
To limit words, am using the following little code :
$string = "hello world ! I love chocolate.";
$explode = array_slice(explode(' ', $string), 0, 4);
$implode = implode(" ",$explode);
echo $implode;
$implot will give : hello world ! I

- 21
- 1
function getShortString($string,$wordCount,$etc = true)
{
$expString = explode(' ',$string);
$wordsInString = count($expString);
if($wordsInString >= $wordCount )
{
$shortText = '';
for($i=0; $i < $wordCount-1; $i++)
{
$shortText .= $expString[$i].' ';
}
return $etc ? $shortText.='...' : $shortText;
}
else return $string;
}

- 183
- 1
- 12
Simpler than all previously posted regex techniques, just match the first n sequences of non-word followed by sequences of word characters. Making the non-word characters optional allows matching of word characters from the start of the string. Greedy word character matching ensures that consecutive word characters are never treated as individual words.
By writing \K
in the pattern after matching n substrings, then matching the rest of the string (add the s
pattern modifier if you need dots to match newlines), the replacement can be an empty string.
Code: (Demo)
function firstNWords(string $string, int $limit = 3) {
return preg_replace("/(?:\W*\w+){{$limit}}\K.*/", '', $string);
}

- 43,625
- 12
- 83
- 136
Here is what I have implemented.
function summaryMode($text, $limit, $link) {
if (str_word_count($text, 0) > $limit) {
$numwords = str_word_count($text, 2);
$pos = array_keys($numwords);
$text = substr($text, 0, $pos[$limit]).'... <a href="'.$link.'">Read More</a>';
}
return $text;
}
As you can see it is based off karim79's answer, all that needed changing was that the if statement also needed to check against words not characters.
I also added a link to main function for convenience. So far it hsa worked flawlessly. Thanks to the original solution provider.

- 983
- 3
- 16
- 31
Here's one I use:
$truncate = function( $str, $length ) {
if( strlen( $str ) > $length && false !== strpos( $str, ' ' ) ) {
$str = preg_split( '/ [^ ]*$/', substr( $str, 0, $length ));
return htmlspecialchars($str[0]) . '…';
} else {
return htmlspecialchars($str);
}
};
return $truncate( $myStr, 50 );

- 2,443
- 2
- 24
- 26
Lets assume we have the string variables $string, $start, and $limit we can borrow 3 or 4 functions from PHP to achieve this. They are:
- script_tags() PHP function to remove the unnecessary HTML and PHP tags (if there are any). This wont be necessary, if there are no HTML or PHP tags.
- explode() to split the $string into an array
- array_splice() to specify the number of words and where it'll start from. It'll be controlled by vallues assigned to our $start and $limit variables.
and finally, implode() to join the array elements into your truncated string..
function truncateString($string, $start, $limit){ $stripped_string =strip_tags($string); // if there are HTML or PHP tags $string_array =explode(' ',$stripped_string); $truncated_array = array_splice($string_array,$start,$limit); $truncated_string=implode(' ',$truncated_array); return $truncated_string; }
It's that simple..
I hope this was helpful.

- 729
- 7
- 10
-
What does this add that the literally dozens of answers this question already has doesn't? – GordonM Jun 20 '18 at 14:02
function limitText($string,$limit){
if(strlen($string) > $limit){
$string = substr($string, 0,$limit) . "...";
}
return $string;
}
this will return 20 words. I hope it will help

- 1
- 1

- 3
- 5
I made my function:
function summery($text, $limit) {
$words=preg_split('/\s+/', $text);
$count=count(preg_split('/\s+/', $text));
if ($count > $limit) {
$text=NULL;
for($i=0;$i<$limit;$i++)
$text.=$words[$i].' ';
$text.='...';
}
return $text;
}

- 503
- 5
- 11
$text='some text';
$len=strlen($text);
$limit=500;
// char
if($len>$limit){
$text=substr($text,0,$limit);
$words=explode(" ", $text);
$wcount=count($words);
$ll=strlen($words[$wcount]);
$text=substr($text,0,($limit-$ll+1)).'...';
}
-
Welcome to Stack Overflow! Please don't answer just with source code. Try to provide a nice description about how your solution works. See: [stackoverflow.com/help/how-to-answer](https://stackoverflow.com/help/how-to-answer). Thanks! – Matt Ke Mar 05 '19 at 22:21
function wordLimit($str, $limit) {
$arr = explode(' ', $str);
if(count($arr) <= $limit){
return $str;
}
$result = '';
for($i = 0; $i < $limit; $i++){
$result .= $arr[$i].' ';
}
return trim($result);
}
echo wordLimit('Hello Word', 1); // Hello
echo wordLimit('Hello Word', 2); // Hello Word
echo wordLimit('Hello Word', 3); // Hello Word
echo wordLimit('Hello Word', 0); // ''

- 19
- 1
- 4
I would go with explode()
, array_pop()
and implode()
, eg.:
$long_message = "I like summer, also I like winter and cats, btw dogs too!";
$trimmed_message = explode(" ", $long_message, 5); // <-- '5' means 4 words to be returned
array_pop($trimmed_message); //removing last element from exploded array
$trimmed_message = implode(" ", $trimmed_message) . '...';
Result:
I like summer, also...

- 4,302
- 3
- 26
- 27

- 420
- 2
- 6
-
This is not useful because it doesn't recognize words, just string/character length. – mickmackusa Nov 09 '17 at 22:52
function limit_word($start,$limit,$text){
$limit=$limit-1;
$stripped_string =strip_tags($text);
$string_array =explode(' ',$stripped_string);
if(count($string_array)>$limit){
$truncated_array = array_splice($string_array,$start,$limit);
$text=implode(' ',$truncated_array).'...';
return($text);
}
else{return($text);}
}
-
12 answers in two days with only a code sample in a old post. you definitely should read this : https://stackoverflow.com/help/how-to-answer. – Frankich Mar 07 '19 at 14:39
-
Can you explain that further? Why do you need all that code, and what **exactly** does it do? – Nico Haase Mar 07 '19 at 14:50