171

I have a description field in my MySQL database, and I access the database on two different pages, one page I display the whole field, but on the other, I just want to display the first 50 characters. If the string in the description field is less than 50 characters, then it won't show ... , but if it isn't, I will show ... after the first 50 characters.

Example (Full string):

Hello, this is the first example, where I am going to have a string that is over 50 characters and is super long, I don't know how long maybe around 1000 characters. Anyway this should be over 50 characters now ...

Exmaple 2 (first 50 characters):

Hello, this is the first example, where I am going ...
mais-oui
  • 2,691
  • 6
  • 19
  • 15
  • 1
    I just want to point out that an ellipsis is a character: '…' != '...' and represented as … – Brett Santore Nov 25 '15 at 16:22
  • MySQL offers the ability to SUBSTRING your fields, and for the ellipsis you may use a case as : select (case when LENGTH(field) > 50 then CONCAT(SUBSTRING(field, 1, 47), '...') else field end) ... – MediaVince Mar 23 '16 at 16:51
  • You might find [`s($str)->truncate(50)`](https://github.com/delight-im/PHP-Str/blob/8fd0c608d5496d43adaa899642c1cce047e076dc/src/Str.php#L233) or [`s($str)->truncateSafely(50)`](https://github.com/delight-im/PHP-Str/blob/8fd0c608d5496d43adaa899642c1cce047e076dc/src/Str.php#L246) (if you don't want to break words) helpful, as found in [this standalone library](https://github.com/delight-im/PHP-Str). – caw Jul 27 '16 at 00:37

12 Answers12

407

The PHP way of doing this is simple:

$out = strlen($in) > 50 ? substr($in,0,50)."..." : $in;

But you can achieve a much nicer effect with this CSS:

.ellipsis {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

Now, assuming the element has a fixed width, the browser will automatically break off and add the ... for you.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • 4
    I think css way will increase transferred data, not desired for mobile browsers. What's more, you send full text, while some times it should not be available. – szamil Feb 11 '14 at 11:36
  • 22
    The main problem I have encountered with the CSS alternative is that it doesn't work for multiline. If your 50 characters wraps over 2 lines, well, say good bye to the second line. Unless there is an alternative I haven't found yet? *Hopes* –  Aug 06 '14 at 05:58
  • 6
    Please note, that for non-basic characters (multibyte) like `á, ň, š, ü,` use multibyte safe - `mb_substr()` instead of `substr()` - btw it can be used just the same - http://php.net/manual/en/function.mb-substr.php – jave.web Dec 30 '15 at 07:30
  • 3
    what about when your text is on multiple lines? – Paranoid Android Mar 15 '16 at 12:30
  • For multiline text you could use white-space: pre-wrap and a fixed height of like two times the line-height. So it will show the "..." at the end of the second line. Works for me so far :3 – Keenora Fluffball Feb 13 '17 at 14:38
  • 2
    @JustPlainHigh Unfortunately the only reliable option for multiline overflow ellipses at this point are JavaScript plugins. The one I've used with good success is for jQuery https://github.com/tbasse/jquery-truncate – Gavin Jul 10 '17 at 20:17
  • strlen($in) > 18 ? substr($in,0,10)."...".substr($in, -8, 8) : $in; this will print a string with first 10 chars and last 8 chars with '...' inside. – herbertD Dec 12 '17 at 15:26
  • Wouldn't be nicer to use the special character "…" instead of 3 consecutive "." in your code ? – Takit Isy Feb 28 '18 at 13:34
  • @TakitIsy Quite possibly, but I still recommend the CSS option. – Niet the Dark Absol Feb 28 '18 at 16:17
242

You can achieve the desired trim in this way too:

mb_strimwidth("Hello World", 0, 10, "...");

Where:

  • Hello World: the string to trim.
  • 0: number of characters from the beginning of the string.
  • 10: the length of the trimmed string.
  • ...: an added string at the end of the trimmed string.

This will return Hello W....

Notice that 10 is the length of the truncated string + the added string!

Documentation: http://php.net/manual/en/function.mb-strimwidth.php

To avoid truncating words:

In case of presenting text excerpts, probably truncating a word should be avoided. If there is no hard requirement on the length of the truncated text, apart from wordwrap() mentioned here, one can use the following 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

jim_kastrin
  • 4,830
  • 2
  • 26
  • 28
  • 5
    Definitely the easiest solution when CSS isn't an option. – Guillochon Feb 19 '14 at 16:20
  • 7
    Elegant solution. As seen in [these comments](http://php.net/manual/en/function.define.php). To prevent a trailing space between the truncated text and the ellipsis, you may want to use rtrim(mb_strimwidth($string, 0, 24))."..." – Tod Birdsall Sep 01 '15 at 20:11
  • 1
    Best option IMHO as CSS is great but for AJAX sometimes you want to exchange the least data possible! – MediaVince Mar 23 '16 at 16:30
  • 10
    OT: Please use `…` instead of three dots. – Dmitri Pisarev Mar 28 '18 at 08:33
  • @jim_kastrin ellipsis Unicode character is a perfectly valid string. – Dmitri Pisarev Mar 28 '18 at 12:48
  • 2
    @jim_kastrin it does not improve the essence of the answer, thus my comment has been marked with Off Topic. But it's a typographical blasphemy to use three dots as an ellipsis, equal to using wrong spelling in an answer. – Dmitri Pisarev Mar 29 '18 at 09:10
  • 1
    @Dmitri Dmitri An ellipsis may not === three dots, but it definitely == three dots. :) – Andrew Feb 27 '19 at 14:15
  • Even though the initial remark on typography was totally off-topic from the start, I still removed my past answers to this point, as I believe it bears no fruit and would pollute almost every answer in this community, if all answers were to be scanned for typographical compliance. Arguments on typography should be their own topic or meta. – jim_kastrin Feb 27 '19 at 15:49
  • But this is cutting words.... certainly UNDESIRED.. – Martin Zvarík Jun 13 '20 at 20:09
  • @MartinZvarík this is the behavior, as explained on the php manual: mb_strimwidth — Get truncated string with specified width. This answers the question how to show the 50 first characters. Of course there may be preferable solutions based on the use case, but that was the original question. – jim_kastrin Jun 14 '20 at 09:52
  • @MartinZvarík besides there are no words when previewing genetic code or a minified js code, therefore it is not cast in stone it is always undesired. – jim_kastrin Jun 14 '20 at 09:56
  • @jim_kastrin The question contains full sentence example... not some genetic code you talking about out of blue – Martin Zvarík Jun 14 '20 at 20:56
  • @MartinZvarik user asks how 'to display the first 50 characters', which is the essence of the question. I only mentioned example use cases to debunk your certainty on this being certainly undesired. Of course, if the case is to present an item description preview on e-commerce, wordwrap() is most probably the way to go, but the question was not more specific. Therefore I cannot be *certain* all cases are like that. – jim_kastrin Jun 15 '20 at 07:53
  • As avoiding word truncation may be common, edited answer to add an approach to avoid word truncation with a different take than wordwrap(). Thanks! – jim_kastrin Jun 15 '20 at 18:43
  • One more check would be needed as this solution gives an empty string if the limit `50` is right on the input last word. Try with `$text = "Knowledge is a natural right of every human being lastword.";` – sglessard Nov 12 '21 at 19:44
51

Use wordwrap() to truncate the string without breaking words if the string is longer than 50 characters, and just add ... at the end:

$str = $input;
if( strlen( $input) > 50) {
    $str = explode( "\n", wordwrap( $input, 50));
    $str = $str[0] . '...';
}

echo $str;

Otherwise, using solutions that do substr( $input, 0, 50); will break words.

nickb
  • 59,313
  • 13
  • 108
  • 143
17
if (strlen($string) <=50) {
  echo $string;
} else {
  echo substr($string, 0, 50) . '...';
}
Tchoupi
  • 14,560
  • 5
  • 37
  • 71
9
<?php
function truncate($string, $length, $stopanywhere=false) {
    //truncates a string to a certain char length, stopping on a word if not specified otherwise.
    if (strlen($string) > $length) {
        //limit hit!
        $string = substr($string,0,($length -3));
        if ($stopanywhere) {
            //stop anywhere
            $string .= '...';
        } else{
            //stop on a word.
            $string = substr($string,0,strrpos($string,' ')).'...';
        }
    }
    return $string;
}
?>

I use the above code snippet many-a-times..

verisimilitude
  • 5,077
  • 3
  • 30
  • 35
4

I use this solution on my website. If $str is shorter, than $max, it will remain unchanged. If $str has no spaces among first $max characters, it will be brutally cut at $max position. Otherwise 3 dots will be added after the last whole word.

function short_str($str, $max = 50) {
    $str = trim($str);
    if (strlen($str) > $max) {
        $s_pos = strpos($str, ' ');
        $cut = $s_pos === false || $s_pos > $max;
        $str = wordwrap($str, $max, ';;', $cut);
        $str = explode(';;', $str);
        $str = $str[0] . '...';
    }
    return $str;
}
Arsen K.
  • 5,494
  • 7
  • 38
  • 51
3
$string = "Hello, this is the first example, where I am going to have a string that is over 50 characters and is super long, I don't know how long maybe around 1000 characters. Anyway this should be over 50 characters know...";

if(strlen($string) >= 50)
{
    echo substr($string, 50); //prints everything after 50th character
    echo substr($string, 0, 50); //prints everything before 50th character
}
Nikola K.
  • 7,093
  • 13
  • 31
  • 39
3

This will return a given string with ellipsis based on WORD count instead of characters:

<?php
/**
*    Return an elipsis given a string and a number of words
*/
function elipsis ($text, $words = 30) {
    // Check if string has more than X words
    if (str_word_count($text) > $words) {

        // Extract first X words from string
        preg_match("/(?:[^\s,\.;\?\!]+(?:[\s,\.;\?\!]+|$)){0,$words}/", $text, $matches);
        $text = trim($matches[0]);

        // Let's check if it ends in a comma or a dot.
        if (substr($text, -1) == ',') {
            // If it's a comma, let's remove it and add a ellipsis
            $text = rtrim($text, ',');
            $text .= '...';
        } else if (substr($text, -1) == '.') {
            // If it's a dot, let's remove it and add a ellipsis (optional)
            $text = rtrim($text, '.');
            $text .= '...';
        } else {
            // Doesn't end in dot or comma, just adding ellipsis here
            $text .= '...';
        }
    }
    // Returns "ellipsed" text, or just the string, if it's less than X words wide.
    return $text;
}

$description = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quibusdam ut placeat consequuntur pariatur iure eum ducimus quasi perferendis, laborum obcaecati iusto ullam expedita excepturi debitis nisi deserunt fugiat velit assumenda. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Incidunt, blanditiis nostrum. Nostrum cumque non rerum ducimus voluptas officia tempore modi, nulla nisi illum, voluptates dolor sapiente ut iusto earum. Esse? Lorem ipsum dolor sit amet, consectetur adipisicing elit. A eligendi perspiciatis natus autem. Necessitatibus eligendi doloribus corporis quia, quas laboriosam. Beatae repellat dolor alias. Perferendis, distinctio, laudantium? Dolorum, veniam, amet!';

echo elipsis($description, 30);
?>
Lucas Bustamante
  • 15,821
  • 7
  • 92
  • 86
2
<?php
$string = 'This is your string';

if( strlen( $string ) > 50 ) {
   $string = substr( $string, 0, 50 ) . '...';
}

That's it.

Berry Langerak
  • 18,561
  • 4
  • 45
  • 58
2
// this method will return the break string without breaking word
$string = "A brown fox jump over the lazy dog";
$len_required= 10;
// user strip_tags($string) if string contain html character
if(strlen($string) > 10)
{
 $break_str = explode( "\n", wordwrap( $string , $len_required));
 $new_str =$break_str[0] . '...';
}
// other method is use substr 
Ramprasath Selvam
  • 3,868
  • 3
  • 25
  • 41
Rehan Rajpoot
  • 158
  • 2
  • 6
1

You can use str_split() for this

$str = "Hello, this is the first example, where I am going to have a string that is over 50 characters and is super long, I don't know how long maybe around 1000 characters. Anyway this should be over 50 characters know...";
$split = str_split($str, 50);
$final = $split[0] . "...";
echo $final;
Nikola K.
  • 7,093
  • 13
  • 31
  • 39
alfrodo
  • 159
  • 6
0

For some of you who uses Yii2 there is a method under the hood yii\helpers\StringHelper::truncate().

Example of usage:

$sting = "stringToTruncate";
$truncatedString = \yii\helpers\StringHelper::truncate($string, 6, '...');
echo $truncatedString; // result: "string..."

Here is the doc: https://www.yiiframework.com/doc/api/2.0/yii-helpers-basestringhelper#truncate()-detail

Akmal
  • 543
  • 7
  • 13