Truncate a string to first n characters of a string and add three dots if any characters are removed
Asked Answered
I

21

382

How can I get the first n characters of a string in PHP? What's the fastest way to trim a string to a specific number of characters, and append '...' if needed?

Intertidal answered 1/7, 2010 at 21:28 Comment(5)
might be better to use the ellipsis character …Coady
theunixshell.blogspot.in/2012/12/…Huskamp
Try This Link, May help You... https://mcmap.net/q/88162/-making-sure-php-substr-finishes-on-a-word-not-a-characterVesuvian
Here is a good comparison of multiple techniques: Truncate a multibyte String to n chars.Spadix
Please indicate if you are going to handle multi-byte strings like at least one letter with an accent like à etc. I know that this is an old question but that would clarify how people should consolidate the answers here. Thanks :)Haily
R
677
//The simple version for 10 Characters from the beginning of the string
$string = substr($string,0,10).'...';

Update:

Based on suggestion for checking length (and also ensuring similar lengths on trimmed and untrimmed strings):

$string = (strlen($string) > 13) ? substr($string,0,10).'...' : $string;

So you will get a string of max 13 characters; either 13 (or less) normal characters or 10 characters followed by '...'

Update 2:

Or as function:

function truncate($string, $length, $dots = "...") {
    return (strlen($string) > $length) ? substr($string, 0, $length - strlen($dots)) . $dots : $string;
}

Update 3:

It's been a while since I wrote this answer and I don't actually use this code any more. I prefer this function which prevents breaking the string in the middle of a word using the wordwrap function:

function truncate($string,$length=100,$append="…") {
  $string = trim($string);

  if(strlen($string) > $length) {
    $string = wordwrap($string, $length);
    $string = explode("\n", $string, 2);
    $string = $string[0] . $append;
  }

  return $string;
}
Rosellaroselle answered 1/7, 2010 at 21:30 Comment(6)
might be best to replace with ellipsis ( … ) rather than 3 dots ( ... )Coady
I love this, but I changed it and use the following to remove whitespace at the end: $string = substr(trim($string),0,10).'...'; That way you get something like "I like to..." instead of "I like to ...".Demetri
"hellip" - took me sometime to understand we were not talking about satan's ip adressAcademic
In case there is a hard cap on the length of the returned string, shouldn't line 5 of update 3 be $string = wordwrap($string, $length - sizeof($append)); ?Intercalary
is this multibyte safe?Dalrymple
No @TimoHuovinen - this is not multibyte safe. And should be declared in the answer but the edit queue is full now, as usual to me.Haily
I
159

This functionality has been built into PHP since version 4.0.6. See the docs.

echo mb_strimwidth('Hello World', 0, 10, '...');

// outputs Hello W...

Note that the trimmarker (the ellipsis above) are included in the truncated length.

Inhabitant answered 3/7, 2014 at 22:56 Comment(3)
WARNING: mb_strimwidth() requires the Multibyte String extension to be installed and activated and that's not always the case so test before deploying.Practicable
Depending on your use-case, be careful with mb_strimwidth(), as a string's length (number of characters it contains) may not be the same as its width: CJK chars can be half- or full-width. Example: plain ascii ab: bytes=2, chars=2, width=2, western unicode éö: bytes=4, chars=2, width=2, katakana Wo, half and full width) ヲヲ: bytes=6, chars=2, width=3Bainter
We should probably mention in an explicit way in the answer that this is multibyte safe. So this is the only correct solution to handle wild user input. Indeed it's not the solution if you are interested in handling binary strings. But the question is a bit vague now. I cannot clarify this right now since the edit queue is full now, as usual to me.Haily
Z
15

The Multibyte extension can come in handy if you need control over the string charset.

$charset = 'UTF-8';
$length = 10;
$string = 'Hai to yoo! I like yoo soo!';
if(mb_strlen($string, $charset) > $length) {
  $string = mb_substr($string, 0, $length - 3, $charset) . '...';
}
Zedoary answered 1/7, 2010 at 21:35 Comment(1)
This code is adding the three dots to the string? my code it has a link tag <a> and when I link it it will link it together with the three dots which it will come as a different value.Facultative
E
11

sometimes, you need to limit the string to the last complete word ie: you don't want the last word to be broken instead you stop with the second last word.

eg: we need to limit "This is my String" to 6 chars but instead of 'This i..." we want it to be 'This..." ie we will skip that broken letters in the last word.

phew, am bad at explaining, here is the code.

class Fun {

    public function limit_text($text, $len) {
        if (strlen($text) < $len) {
            return $text;
        }
        $text_words = explode(' ', $text);
        $out = null;


        foreach ($text_words as $word) {
            if ((strlen($word) > $len) && $out == null) {

                return substr($word, 0, $len) . "...";
            }
            if ((strlen($out) + strlen($word)) > $len) {
                return $out . "...";
            }
            $out.=" " . $word;
        }
        return $out;
    }

}
Equidistance answered 23/3, 2013 at 8:27 Comment(0)
A
9

If you want to cut being careful to don't split words you can do the following

function ellipse($str,$n_chars,$crop_str=' [...]')
{
    $buff=strip_tags($str);
    if(strlen($buff) > $n_chars)
    {
        $cut_index=strpos($buff,' ',$n_chars);
        $buff=substr($buff,0,($cut_index===false? $n_chars: $cut_index+1)).$crop_str;
    }
    return $buff;
}

if $str is shorter than $n_chars returns it untouched.

If $str is equal to $n_chars returns it as is as well.

if $str is longer than $n_chars then it looks for the next space to cut or (if no more spaces till the end) $str gets cut rudely instead at $n_chars.

NOTE: be aware that this method will remove all tags in case of HTML.

Abercromby answered 17/7, 2013 at 14:45 Comment(0)
I
8

The codeigniter framework contains a helper for this, called the "text helper". Here's some documentation from codeigniter's user guide that applies: http://codeigniter.com/user_guide/helpers/text_helper.html (just read the word_limiter and character_limiter sections). Here's two functions from it relevant to your question:

if ( ! function_exists('word_limiter'))
{
    function word_limiter($str, $limit = 100, $end_char = '&#8230;')
    {
        if (trim($str) == '')
        {
            return $str;
        }

        preg_match('/^\s*+(?:\S++\s*+){1,'.(int) $limit.'}/', $str, $matches);

        if (strlen($str) == strlen($matches[0]))
        {
            $end_char = '';
        }

        return rtrim($matches[0]).$end_char;
    }
}

And

if ( ! function_exists('character_limiter'))
{
    function character_limiter($str, $n = 500, $end_char = '&#8230;')
    {
        if (strlen($str) < $n)
        {
            return $str;
        }

        $str = preg_replace("/\s+/", ' ', str_replace(array("\r\n", "\r", "\n"), ' ', $str));

        if (strlen($str) <= $n)
        {
            return $str;
        }

        $out = "";
        foreach (explode(' ', trim($str)) as $val)
        {
            $out .= $val.' ';

            if (strlen($out) >= $n)
            {
                $out = trim($out);
                return (strlen($out) == strlen($str)) ? $out : $out.$end_char;
            }       
        }
    }
}
Insufficient answered 6/7, 2010 at 1:43 Comment(0)
B
5
if(strlen($text) > 10)
     $text = substr($text,0,10) . "...";
Bristol answered 1/7, 2010 at 21:31 Comment(2)
From @Brendon Bullen above .. $string = (strlen($string) > 13) ? substr($string,0,10).'...' : $string; Nice !Seriatim
This question is correct for binary strings but it's not correct for multibyte strings. The question is a bit vague over its need, so, better to clarify in an explicit way. Unfortunately the edit queue is full now, as usual to me.Haily
I
3

Use substring

http://php.net/manual/en/function.substr.php

$foo = substr("abcde",0, 3) . "...";
Isreal answered 1/7, 2010 at 21:32 Comment(4)
This code will always add ... to the string, which he didn't want.Archbishopric
You're absolutely right, and I edited the answer accordingly. (Revised answer currently awaiting SO peer review)Appurtenant
This answer is not multibyte safe. That is probably OK (since the question does not clarify this need) but better to be declared in the question itself. I cannot add this information since the edit queue is full, as usual to me.Haily
@ChayaCooper your edit was refused by somebody, and the reason is: you probably need to write an if, to then decide whenever to append the .... Instead in your edit you just removed the .... - See the question. I cannot propose a counter-patch now because the edit queue is full now, as usual to me.Haily
N
3

It already has a helper method for it in Laravel 6+ versions. You could simply use that.

\Str::limit('The quick brown fox jumps over the lazy dog', 20);

which gives you output like

The quick brown fox...

For more detail please check laravel official document: https://laravel.com/docs/8.x/helpers#method-str-limit

Nuke answered 20/6, 2023 at 5:3 Comment(0)
F
2

This function do the job without breaking words in the middle

    function str_trim($str,$char_no){
        if(strlen($str)<=$char_no)
            return $str;
        else{
            $all_words=explode(" ",$str);
            $out_str='';
            foreach ($all_words as $word) {
                $temp_str=($out_str=='')?$word:$out_str.' '.$word;
                if(strlen($temp_str)>$char_no-3)//-3 for 3 dots
                    return $out_str."...";
                $out_str=$temp_str;
            }
        }
    }
Finally answered 8/8, 2021 at 10:14 Comment(0)
A
1

It's best to abstract you're code like so (notice the limit is optional and defaults to 10):

print limit($string);


function limit($var, $limit=10)
{
    if ( strlen($var) > $limit )
    {
        return substr($string, 0, $limit) . '...';
    }
    else
    {
        return $var;
    }
}
Archbishopric answered 1/7, 2010 at 21:35 Comment(3)
Could explain why this approach is best instead of just asserting that it is?Leftwards
@Leftwards it's simple, and abstracting means you don't have to retype the code over and over. And most importantly, if you do find a better way to do this, or want something more complex, you only change this 1 function instead of 50 pieces of code.Archbishopric
Fix: substr of $var, not $string. Test against $limit + 3 so that you don't trim a string just over the limit. Depending on your application (e.g., HTML output), consider using an entity &hellip; instead (typographically more pleasing). As suggested earlier, trim off any non-letters from the end of the (shortened) string before appending the ellipsis. Finally, watch out if you're in a multibyte (e.g., UTF-8) environment -- you can't use strlen() and substr().Metallist
S
1

The function I used:

function cutAfter($string, $len = 30, $append = '...') {
        return (strlen($string) > $len) ? 
          substr($string, 0, $len - strlen($append)) . $append : 
          $string;
}

See it in action.

Subtenant answered 21/9, 2011 at 19:59 Comment(1)
This answer is missing its educational explanation.Spadix
T
1

I developed a function for this use

 function str_short($string,$limit)
        {
            $len=strlen($string);
            if($len>$limit)
            {
             $to_sub=$len-$limit;
             $crop_temp=substr($string,0,-$to_sub);
             return $crop_len=$crop_temp."...";
            }
            else
            {
                return $string;
            }
        }

you just call the function with string and limite
eg:str_short("hahahahahah",5);
it will cut of your string and add "..." at the end
:)

Timothee answered 4/2, 2013 at 6:8 Comment(0)
R
1

This is what i do

    function cutat($num, $tt){
        if (mb_strlen($tt)>$num){
            $tt=mb_substr($tt,0,$num-2).'...';
        }
        return $tt;
    }

where $num stands for number of chars, and $tt the string for manipulation.

Ruwenzori answered 21/3, 2013 at 16:56 Comment(0)
I
1

To create within a function (for repeat usage) and dynamical limited length, use:

function string_length_cutoff($string, $limit, $subtext = '...')
{
    return (strlen($string) > $limit) ? substr($string, 0, ($limit-strlen(subtext))).$subtext : $string;
}

// example usage:
echo string_length_cutoff('Michelle Lee Hammontree-Garcia', 26);

// or (for custom substitution text
echo string_length_cutoff('Michelle Lee Hammontree-Garcia', 26, '..');
Insular answered 19/6, 2013 at 17:3 Comment(1)
This answer is missing its educational explanation.Spadix
G
1

I'm not sure if this is the fastest solution, but it looks like it is the shortest one:

$result = current(explode("\n", wordwrap($str, $width, "...\n")));

P.S. See some examples here https://mcmap.net/q/88164/-how-to-truncate-a-string-in-php-to-the-word-closest-to-a-certain-number-of-characters

Grady answered 25/7, 2013 at 8:21 Comment(4)
Thanks but indeed this is an inefficient solution since it calls two parsing functions at least O(N) plus another function, and, unfortunately this is not readable without a comment. Comment that, indeed should be added, to explain this snippet to other people, and so, making this solution not that short :) So probably maybe to have a solution that is a bit longer, but a bit more efficient and/or at least more readable. Also, note that this solution is not multibyte safe and should be declared in the answer, since the question is a bit vague about what they want (but edit queue is full now)Haily
Premising that this kind of answers could be very interesting in Code Golf - codegolf.stackexchange.comHaily
@ValerioBozz Thanks for the constructive criticism. I agree with your concerns regarding that code snippet. Indeed, seven years after I wrote this, I had to refer to the question of this thread to understand what it does! I'll leave my answer as it is to let other people learn from my mistakes.Grady
Don't say "mistake" :) It works so it's not a mistake. It's just very creative :) ehehHaily
T
0

substr() would be best, you'll also want to check the length of the string first

$str = 'someLongString';
$max = 7;

if(strlen($str) > $max) {
   $str = substr($str, 0, $max) . '...';
}

wordwrap won't trim the string down, just split it up...

Toenail answered 1/7, 2010 at 21:42 Comment(0)
M
0

$width = 10;

$a = preg_replace ("~^(.{{$width}})(.+)~", '\\1…', $a);

or with wordwrap

$a = preg_replace ("~^(.{1,${width}}\b)(.+)~", '\\1…', $a);
Maniple answered 26/7, 2013 at 15:50 Comment(1)
This answer is missing its educational explanation.Spadix
K
0

this solution will not cut words, it will add three dots after the first space. I edited @Raccoon29 solution and I replaced all functions with mb_ functions so that this will work for all languages such as arabic

function cut_string($str, $n_chars, $crop_str = '...') {
    $buff = strip_tags($str);
    if (mb_strlen($buff) > $n_chars) {
        $cut_index = mb_strpos($buff, ' ', $n_chars);
        $buff = mb_substr($buff, 0, ($cut_index === false ? $n_chars : $cut_index + 1), "UTF-8") . $crop_str;
    }
    return $buff;
}
Katabatic answered 27/1, 2014 at 13:17 Comment(0)
D
0
$yourString = "bla blaaa bla blllla bla bla";
$out = "";
if(strlen($yourString) > 22) {
    while(strlen($yourString) > 22) {
        $pos = strrpos($yourString, " ");
        if($pos !== false && $pos <= 22) {
            $out = substr($yourString,0,$pos);
            break;
        } else {
            $yourString = substr($yourString,0,$pos);
            continue;
        }
    }
} else {
    $out = $yourString;
}
echo "Output String: ".$out;
Dialectical answered 4/3, 2014 at 13:47 Comment(1)
This answer is missing its educational explanation.Spadix
C
0

If there is no hard requirement on the length of the truncated string, one can use this to truncate and prevent cutting the last word as well:

$text = "Knowledge is a natural right of every human being of which no one
has the right to deprive him or her under any pretext, except in a case where a
person does something which deprives him or her of that right. It is mere
stupidity to leave its benefits to certain individuals and teams who monopolize
these while the masses provide the facilities and pay the expenses for the
establishment of public sports.";

// we don't want new lines in our preview
$text_only_spaces = preg_replace('/\s+/', ' ', $text);

// truncates the text
$text_truncated = mb_substr($text_only_spaces, 0, mb_strpos($text_only_spaces, " ", 50));

// prevents last word truncation
$preview = trim(mb_substr($text_truncated, 0, mb_strrpos($text_truncated, " ")));

In this case, $preview will be "Knowledge is a natural right of every human being".

Live code example: http://sandbox.onlinephpfunctions.com/code/25484a8b687d1f5ad93f62082b6379662a6b4713

Chavez answered 15/6, 2020 at 13:0 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.