[php] How can I truncate a string to the first 20 words in PHP?

How can I truncate a string after 20 words in PHP?

This question is related to php string

The answer is


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.


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--

use PHP tokenizer function strtok() in a loop.

$token = strtok($string, " "); // we assume that words are separated by sapce or tab
$i = 0;
$first20Words = '';
while ($token !== false && $i < 20) {
    $first20Words .= $token;
    $token = strtok(" ");
    $i++;
}
echo $first20Words;

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;
}

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.


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>';

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;
    }

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));

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); // ''

what about

chunk_split($str,20);

Entry in the PHP Manual


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.


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;
 }

}

Try below code,

 $text  = implode(' ', array_slice(explode(' ', $text), 0, 32))
 echo $text;

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;
    }

    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);}
    }

$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)).'...';
    }

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


This looks pretty good to me:

A common problem when creating dynamic web pages (where content is sourced from a database, content management system or external source such as an RSS feed) is that the input text can be too long and cause the page layout to 'break'.

One solution is to truncate the text so that it fits on the page. This sounds simple, but often the results aren't as expected due to words and sentences being cut off at inappropriate points.


Something like this could probably do the trick:

<?php 
$words = implode(' ', array_slice(split($input, ' ', 21), 0, 20));

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]) . '&hellip;';
        } else {
            return htmlspecialchars($str);
        }
    };
    return $truncate( $myStr, 50 );

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;
}

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.


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


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;
} 

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


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(""));  # => ""

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 : '');
}