SitePoint Sponsor

User Tag List

Results 1 to 12 of 12
  1. #1
    SitePoint Evangelist Rodney H.'s Avatar
    Join Date
    Sep 2005
    Location
    Chicago, IL
    Posts
    479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Need help with function (please)

    Hi, I am creating a simple function to limit the length of a string returned from the db using PHP's substr().

    It is as follows:
    PHP Code:
    <?php
    function cutString($string,$length 125) {

        if(
    strlen($string) > $length)
        {
            return 
    substr($string0$length 3) . '...';
        }
        else {
            return 
    $string;
        }
    }
    ?>
    It works fine, but I would like it to prevent cutting words in half when called. can anyone help me modify this so if the string length is long and gets cut, it will not cut a word in half, but will look for the next (or previous) white space to cut it at... ?

    Thanks.

  2. #2
    SitePoint Enthusiast
    Join Date
    Jan 2006
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    A good little article on this:

    http://www.the-art-of-web.com/php/truncate/

  3. #3
    SitePoint Enthusiast spamonkey8's Avatar
    Join Date
    Feb 2006
    Posts
    98
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This should do you:

    PHP Code:
    function cutString($string$length 125)  { 
        if (
    strlen($string) > $length) {
            
    //Note that I changed this to 2 to leave on a trailing space, if present
            
    $string substr($string0$length 2);
        
            
    //This is the last occurence of a space in that truncated string
            
    $pos strrpos($string' ');

            
    //If it found a space
            
    if ($pos !== false) {
                
    //Cut off everything from the last space on
                
    $string substr($string0$pos);
            } else {
                
    //Cut off to make room for the ellipses
                
    $string substr($string0$length 3);
            }
            
    $string .= '...';
        }

        return 
    $string;

    From my tests, it accounts for strings without spaces and strings with a word break at the length threshold. If there's a case I've overlooked, please tell me. Enjoy!

  4. #4
    Always learning kigoobe's Avatar
    Join Date
    May 2004
    Location
    Paris
    Posts
    1,565
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Personally what I do normally is
    PHP Code:
    $string substr($string0125);
    $string substr($string,0,strrpos($string," ")); 
    $etc " ... ";      
    $string $string.$etc
    Short, simple, and it works ...

    But I'll try spamonkey8's way as well, learning new things are never bad !!!

  5. #5
    SitePoint Enthusiast spamonkey8's Avatar
    Join Date
    Feb 2006
    Posts
    98
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The function on the site jackreacher linked to works differently from mine. Mine is made to never return a string longer than length. If you give myTruncate a string that is longer than the threshold length and at the cutoff is either at a space or in a word, it will include the next word.

    Example:
    PHP Code:
    echo myTruncate('This is a test of the functions-blah-blah-blah in PHP!'22);
    echo 
    myTruncate('This is a test of the functions-blah-blah-blah in PHP!'27);
    //Both print out these 49 characters:
    //This is a test of the functions-blah-blah-blah... 
    kigoobe's example isn't meant to be as robust, so it would cut off a word if it ends at the exact cutoff length, print out 127 characters if the cuttof character was a space, always add on the '...' even if it wasn't needed, and return just the '...' for strings without any spaces.

    It usually won't matter how it works, you can tell I just like algorithm analysis.

  6. #6
    SitePoint Enthusiast spamonkey8's Avatar
    Join Date
    Feb 2006
    Posts
    98
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Compacted and revised slightly:
    PHP Code:
    function cutString($string$length 96$suffix '...')  { 
        if (
    strlen($string) <= $length)
            return 
    $string;
        if (
    $length <= strlen($suffix))
            return 
    substr($suffix0$length);

        
    $pos strrpos(substr($string0$length strlen($suffix) + 1), ' ');
        return 
    substr($string0, ($pos !== false) ? $pos $length strlen($suffix)) . $suffix;


  7. #7
    SitePoint Evangelist Rodney H.'s Avatar
    Join Date
    Sep 2005
    Location
    Chicago, IL
    Posts
    479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Great, thanks for the info and ideas, /*edit*/ ALL of you. I appreciate it.

    have a great day.
    Last edited by Rodney H.; Feb 21, 2006 at 17:05.

  8. #8
    SitePoint Guru aamonkey's Avatar
    Join Date
    Sep 2004
    Location
    kansas
    Posts
    953
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    how about:
    PHP Code:
       function cutString($string,$length 125) {
           return 
    preg_replace("#(.{".$length."}.*?\b).*#s""$1..."$string);
       } 

  9. #9
    SitePoint Evangelist Rodney H.'s Avatar
    Join Date
    Sep 2005
    Location
    Chicago, IL
    Posts
    479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey, I have a lot of monkeys in my thread. *cool*

    Hmmm. Looks pretty simple, aamonkey. Will give 'er a try right now.

    Thanks to you, too...

  10. #10
    SitePoint Evangelist Rodney H.'s Avatar
    Join Date
    Sep 2005
    Location
    Chicago, IL
    Posts
    479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    aamonkey,

    That is short and sweet.

    Can you break it down for me a little so I can comment my code? I think I will use this...

    thanks.

  11. #11
    SitePoint Guru aamonkey's Avatar
    Join Date
    Sep 2004
    Location
    kansas
    Posts
    953
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    sure,

    the regex looks like this:

    #(.{125}.*?\b).*#s

    the # signs are a delimiter -- they just say we're starting and stopping the expression (you could use about any character for this, i just happen to be partial to # signs ).

    .{125} -- a . means "any character", and {125} means 125 of the preceding, so 125 of any characters

    .*? -- the * means "any number of" and the "?" (used in this context) means to use "ungreedy matching. so any number of any character, ungreedy.

    \b -- a word boundary

    the () around all this means to capture everything inside as a subpattern...more on this later.

    then the .* again means "any number of any characters"--we don't capture this in a subpattern because this is the part we want to delete.

    So we are capturing 125 of any characters, then anything until we hit a word boundary. This is captured in the first subpattern with the () and is assigned to the variable $1 (a second subpattern would be assigned to $2, etc.)

    So we replace the original string with "$1..." meaning the first captured subpattern followed by 3 dots.

    the s modifier at the end of the expression means the . character matches newlines, too (it normally matches anything BUT newlines). This you may or may not want to use, depending on your source string.

    hth--I'm a lot better at writing regexs than explaining them

  12. #12
    SitePoint Evangelist Rodney H.'s Avatar
    Join Date
    Sep 2005
    Location
    Chicago, IL
    Posts
    479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Oh *brilliant*.

    Thanks loads.

    I am so glad I posted this, as I read the article, played around with variations of my function suggested by the other posts, and how learned some regex ( have been meaning to get better at them...).

    Multi Grazie!


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •