Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : String Functions : wordwrap

wordwrap

Wraps a string to a given number of characters (PHP 4 >= 4.0.2, PHP 5)
string wordwrap ( string str [, int width [, string break [, bool cut]]] )

Example 2485. wordwrap() example

<?php
$text
= "The quick brown fox jumped over the lazy dog.";
$newtext = wordwrap($text, 20, "<br />\n");

echo
$newtext;
?>

The above example will output:

The quick brown fox<br />
jumped over the lazy<br />
dog.

Example 2486. wordwrap() example

<?php
$text
= "A very long woooooooooooord.";
$newtext = wordwrap($text, 8, "\n", true);

echo
"$newtext\n";
?>

The above example will output:

A very
long
wooooooo
ooooord.

Code Examples / Notes » wordwrap

kyle

Yet-another-wordwrap-improvement... If you attempt to wordwrap() lines that already contain some line-breaks that you want to maintain, a simple wrapper around wordwrap can help. For example:
function preserve_wordwrap($tstr, $len = 75, $br = '\n') {
    $strs = explode($tstr,$br);
    $retstr = "";
    foreach ($strs as $str) {
         $retstr .= wordwrap($str,$len,$br) . $br;
    }
    return $retstr;
}
I used a function like this for pulling quotes for my email out of a mysql database and formatting them for use in an email. Some quotes had multiple lines (e.g. a short conversation-style quote) that I wanted to maintain yet still word-wrap correctly.


lteague

Yet Another wordwrap replacement-- this one only splits words if the actual word is longer than $cols, not the line, and it does not break up HTML tags. Perfect for when all you really want to do is prevent malicious message board posts.
function wordwrap2($str,$cols,$cut) {
 $len=strlen($str);
 
 $tag=0;
 for ($i=0;$i<$len;$i++) {
   $chr = substr($str,$i,1);
   if ($chr=="<")
     $tag++;
   elseif ($chr==">")
     $tag--;
   elseif (!$tag && $chr==" ")
     $wordlen=0;
   elseif (!$tag)
     $wordlen++;
   if (!$tag && !($wordlen%$cols))
     $chr .= $cut;
   
   $result .= $chr;
 }
   
 return $result;
 
}


sheepsatmindless.com

Wordwrap nonproportional fonts! and exclude html tags!
If you have a problem with PHP' worwrap which you aren't able to give
arguments for NOT parsing through some string parts (like html codes,
which could be longer then ie.80 chars), here's how to do it.
This function, cuts words in $str longer then $cols long, and puts and $cut in
it. It escapes everything whitin "<>".
So "<longggggggggggggtext>" will not be cutted, and just
"longggggggggggggtext", will be cutted! :)
This one can also try to work with nonproportional fonts. Like Arial and Verdana, instead of only fixed fonts.
$str = the string you want to process.
$cols = choose ie.80 for prop.fonts
       choose ie.450 for non prop fonts
       NOTE: $cols are not pixels!
$non_prop = choose "true" for arial,verdana etc.
           false = fixed (courier)
$exclude1 = excludesystem, read the begin of this note. enter '<'
$exclude2 = enter '>'
function sheep_wordwrap($str,$cols,$non_prop,$cut,$exclude1,$exclude2){
 $count=0;
 $tagcount=0;
 $str_len=strlen($str);
 //$cut=" $cut ";
 $calcwidth=0;
 
 for ($i=1; $i<=$str_len;$i++){
   $str_len=strlen($str);
   if ($str[$i]==$exclude1)
     $tagcount++;
   elseif ($str[$i]==$exclude2){
     if ($tagcount>0)
       $tagcount--;
   }
   else{
     if (($tagcount==0)){
       if (($str[$i]==' ') || ($str[$i]=="\n"))
         $calcwidth=0;
       else{
         if ($non_prop){
           if (ereg("([QWOSDGCM#@m%w]+)",$str[$i],$matches))
             $calcwidth=$calcwidth+7;
           elseif (ereg("([I?\|()\"]+)",$str[$i],$matches))
             $calcwidth=$calcwidth+4;
           elseif (ereg("([i']+)",$str[$i],$matches))
             $calcwidth=$calcwidth+2;
           elseif (ereg("([!]+)",$str[$i],$matches))
             $calcwidth=$calcwidth+3;
           else{
             $calcwidth=$calcwidth+5;
           }
         }
         else{
           $calcwidth++;
         }
         if ($calcwidth>$cols){
           $str=substr($str,0,$i-1).$cut.substr($str,$i,$str_len-1);
           $calcwidth=0;
         }
       }
     }
   }
 }
 return $str;
 //moby rules at 5am! :)
}


andrej dot pavlovic

Wordwrap for utf8. Easy to understand and works with the $cut parameter:
<?php
function utf8_wordwrap($str,$width=75,$break="\n", $cut=false){
   return utf8_encode(wordwrap(utf8_decode($str), $width, $break, $cut));
}
?>


sych

wordwrap doesn't know about UTF and considers a multi-byte utf characters as as many characters as there are bytes in there. However, it will still break correctly on " " and "#" (or all other characters in the ascii range (0-127).
However, this is not a bug as it was only meant to work on iso-8859-*.


tjomi4

utf8_wordwrap();
usage: utf8_wordwrap("text",3,"
");
coded by tjomi4`, thanks to SiMM.
web: www.yeap.lv
<?php
function utf8_wordwrap($str,$len,$what){
# usage: utf8_wordwrap("text",3,"
");
# by tjomi4`, thanks to SiMM.
# www.yeap.lv
$from=0;
$str_length = preg_match_all('/[\x00-\x7F\xC0-\xFD]/', $str, $var_empty);
$while_what = $str_length / $len;
while($i <= round($while_what)){
$string = preg_replace('#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'.$from.'}'.
                      '((?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'.$len.'}).*#s',
                      '$1',$str);
$total .= $string.$what;
$from = $from+$len;
$i++;
}
return $total;
}
?>


frans-jan

Using wordwrap is usefull for formatting email-messages, but it has a disadvantage: line-breaks are often treated as whitespaces, resulting in odd behaviour including lines wrapped after just one word.
To work around it I use this:
<?php
function linewrap($string, $width, $break, $cut) {
 $array = explode("\n", $string);
 $string = "";
 foreach($array as $key => $val) {
  $string .= wordwrap($val, $width, $break, $cut);
  $string .= "\n";
 }
 return $string;
}
?>
I then use linewrap() instead of wordwrap()
hope this helps someone


vex

Useful in chat's, shoutboxes sth. like that (simply written):
$text = explode(" ", $text);
$l=count($text);
$counter=0;
while($counter<=$l) {
$text[$counter] = wordwrap($text[$counter], 20, " ", 1);
$counter++;
}
$text=implode(" ", $text);


lean -- roico

To @Anthony Catel
Wouldn't be easier, more correct and more simple to cut the words having more characters than the $limit parameter like the following code?
<?
function cut_words( $txt , $limit, $html_nl = 0 )
{
$str_nl = $html_nl == 1 ? "
" : ( $html_nl == 2 ? "<br />" : "\n" );
$pseudo_words = explode( ' ',$txt );
$txt = '';
foreach( $pseudo_words as $v )
{
if( ( $tmp_len = strlen( $v ) ) > $limit )
{
$final_nl = is_int( $tmp_len / $limit );
$txt .= chunk_split( $v, $limit, $str_nl );
if( !$final_nl )
$txt = substr( $txt, 0, - strlen( $str_nl ) );
$txt .= ' ';
}
else
$txt .= $v . ' ';
}
return substr( $txt, 0 , -1 );
}
?>
For using it this is a sample:
<?
function cut_words( 'big words text here' , 15, 2 );
?>


info ät travelguides24.com

this one is nice, because it does not put any linebreaks or empty spaces if there is enough space. It is not propper html as seen by validator.w3.org, but it works on IE and Moz.
function splitLongWords($text, $max) {
   return preg_replace( '/([^\s]{'.$max.'})(?=[^\s])/', '$1<wbr>', $text);
}


matyx666

This function wraps a string with the characters count specified:
static function cortarCaracteres($sText, $iCharsCount, $sCutWith = "...") {
$sTextLength = strlen($sText);
if($sTextLength <= $iCharsCount) {
return $sText;
}
if($sTextLength+strlen($sCutWith) > $iCharsCount) {
return substr($sText, 0, $iCharsCount-strlen($sCutWith)).$sCutWith;
}
$iLeftOverChars = strlen($sCutWith) - ($sTextLength - $iCharsCount);
return substr($sText, 0, $sTextLength-$iLeftOverChars).$sCutWith;
}
Regards!


info*at*cirgo*dot*com

There was a little bug in the modification of Jeffrey Sambells wordwrap function writen by Alex of oxyscripts.com...
The modified function would cut off the last character of the first half of the clipped string.
The line that reads:
$str = substr($str,0,$i).$cut.substr($str,$i+1,$str_len-1);
Needs to be:
$str = substr($str,0,$i+1).$cut.substr($str,$i+1,$str_len-1);
At least it does on WIN32 platform.
-Billy Olson
http://www.cirgo.com


ophir prusak

There is an error in the documentation. The docs currently say:
If the cut is set to 1, the string is always wrapped at the specified width. So if you have a word that is larger than the given width, it is broken apart. (See second example).
It should be something like this:
If the cut is set to 1, words longer than the given width will be wrapped at the specified width, otherwise they will not be wrapped at all. Words that are not longer than width are not effected by the cut parameter.
Ophir Prusak


philip

There is a wordwrap() alternative found here :
http://morannon.the-infinite.org/archive/php/word_wrap


desolate19

The wordwrap2 function posted by lteague is exactly what I was looking for.  Unfortunatly it has an error.  It will add the cut string any time a space is encountered outside of a tag since
(!(0 % x)), where x != 0, is always true.
Here's a fixed function with a few other improvments.  Again this function will split a word that is longer that $cols and is outside any HTML tags by the string $cut.  Lines with whitespace in them are ok, only single words over $cols lenght are split.
function wordwrap2($str, $cols, $cut)
{
   $len = strlen($str);
   $tag = 0;
   for ($i = 0; $i < $len; $i++) {
       $chr = $str[$i];
       if ($chr == '<') {
           $tag++;
       } elseif ($chr == '>') {
           $tag--;
       } elseif ((!$tag) && (ctype_space($chr))) {
           $wordlen = 0;
       } elseif (!$tag) {
           $wordlen++;
       }
       if ((!$tag) && ($wordlen) && (!($wordlen % $cols))) {
           $chr .= $cut;
       }
       $result .= $chr;
   }
   return $result;
}


peter

The main concern when you have a text in a cell is for long words that drags the cell margins. This function will break words in a text that have more then $nr characters using the "-" char.
function processtext($text,$nr=10)
{
$mytext=explode(" ",trim($text));
$newtext=array();
foreach($mytext as $k=>$txt)
{
if (strlen($txt)>$nr)
{
$txt=wordwrap($txt, $nr, "-", 1);
}
$newtext[]=$txt;
}
return implode(" ",$newtext);
}


ab_at_notenet dot dk

The function for wrapping strings without wrapping the html might need a second parameter (lenght):
<?php
function textWrap($text, $size = 90) {
$new_text = '';
$text_1 = explode('>',$text);
$sizeof = sizeof($text_1);
for ($i=0; $i<$sizeof; ++$i) {
$text_2 = explode('<',$text_1[$i]);
if (!empty($text_2[0])) {
$new_text .= preg_replace('#([^\n\r .]{'. $size .'})#i', '\\1  ', $text_2[0]);
}
if (!empty($text_2[1])) {
$new_text .= '<' . $text_2[1] . '>';  
}
}
return $new_text;
}
?>


x403

String lenght control:
if (str_word_count($STRING) > 0)
$div = strlen($STRING) / str_word_count($STRING);
else return " ";
if ( $div > 25 ) return wordwrap($STRING, 25, "\n", 1);
return $STRING;
// Maximum word lenght is 25 chars


me

please improve this function i have made to wrap text wider than $need_width pixels...
function wrap_pix($text,$need_width,$separator,$font,$font_size,
      $dim){
   $len = strlen($text);
   $width = 65000;
   $len_left = $interval = floor($len/2);
   do {
       $left = substr($text,0,$len_left);
       if ($left[0] == " ") {
           $left = substr($left,1);
           $text = substr($text,1);
       }
       if ( $left[strlen($left)] == " "){
           $left = substr($left,0,strlen($left)-1);
       }
       $size = imagettfbbox($font_size,0,$font,$left);
       $width = abs($size[2] - $size[0]);
       $interval = 1 > floor($interval/2) ? 1 : floor($interval/2);
       if ( $width <= $need_width-$dim && strlen($left)!=strlen($text)){
           $to = $len < strlen($left)+$interval ? $len : strlen($left)+$interval;
           $left = substr($text,0,$to);
           $len_left = strlen($left);
           continue;
       }
       if ( $width > $need_width+$dim ){
           $left = substr($text,0,strlen($left)-$interval);
           $len_left = strlen($left);
           continue;
       }
   } while ( (($width <= $need_width-$dim) || ($width >
$need_width+$dim)) && strlen($text) != strlen($left));
   if ( $width > $need_width ){
       if (strrchr($left," ")){
           $newlen = strlen($left) - strlen(strrchr($left," "));
           $left = substr($left,0,$newlen).$separator;
           $minus=0;
       }
       else{
           $left = substr($left,0,$len_left-2)."-".$separator;
           $minus = 1;
       }
   }
   if ( $width <= $need_width){
       if ( preg_match("/\.,\-\s\"\'/i",$text[strlen($left)+1])){
           $tmp = substr($text,0,strlen($left)+1);
           $size = imagettfbbox($fontsize,0,$font,$tmp);
           $width = abs($size[2] - $size[0]);
           if ( $width < $need_width ) $left = $tmp;
       }
       else if ( !preg_match("/\.,\-\s\"\'/i",$text[strlen($left)])){
               $newlen = strlen($left) - strlen(strrchr($left," "));
               $left = substr($left,0,$newlen).$separator;
            }
   }
   if (strlen($text)!=0) {
       $return=wrap_pix( substr($text,(strlen($left)-strlen($separator)-$minus)),
             $need_width,$separator,$font,$font_size,$dim);
       $left.=$return;
   }
   return $left;
}


cdblog

note:
if you can't see the example, please change your browser's default encode to Chinese Simplified (GB2312). :)
also, this function maybe will work at other double-bytes language, such as Korean.
<?php
/**
* @return string
* @author Cocol
* @desc the wordwrap for Chinese ,Janpanese
* for more detail please visit http://php.clickz.cn/articles/string/wrodwrap.html
*/
function wordwrap_cn($str = "",$len = 80,$glue = "\n") {
for ($i=0;$i<strlen($str);$i++) {
if (ord(substr($str,$i,1)) > 128) {
$str_arr[] = substr($str,$i,2);
$i++;
} else {
$str_arr[] = substr($str,$i,1);
}
}
$tmp = array_chunk($str_arr,$len);
$str = "";
foreach ($tmp as $key=>$val) {
$str .= implode("",$val).$glue;
}
return $str;
}
//example 1: Chinese test
$str = "ËüÊÕ¼ÁËÈ«Çò×ÊѶÍøÉÏÊýÒÔÍò¼ÆµÄÖÐÎÄÍøÕ¾£¬²»ÂÛ";
print wordwrap_cn($str,10);
// will output
/*
ËüÊÕ¼ÁËÈ«Çò×ÊѶÍøÉÏ
ÊýÒÔÍò¼ÆµÄÖÐÎÄÍøÕ¾£¬
²»ÂÛ
//example 2: Janpanese test
*/ $str = "±¦‰VÓ›Äî¤Ë³ö×ߤµ¤»¤¿¤¤ñR¤ËͶƱ¤ò";
print wordwrap_cn($str,10);
// will output
/*
±¦‰VÓ›Äî¤Ë³ö×ߤµ¤»¤¿
¤¤ñR¤ËͶƱ¤ò
*/
?>


09-may-2005 06:33

Note that wordwrap is meant for...wrapping words.  If you're simply trying to break a string into evenly sized pieces, take a look at chunk_split and str_split.

me

luismorrison's function will split a string into a first and second line *only*. If your string is 100 characters long and you wrap at 30 characters you will end up with 30 chars on line 1 and 70 on line 2.
I've included an English translation here for reference as I was going round the bend trying to figure it out in Spanish! :)
<?php
   function splitstroverflow($chain,$length) {
       $pri_line = array();
       $seg_line = array();
       $words = explode(" ",trim($chain));
     
       for ($i = 0; $i < count($words); $i++) {
           $sum += strlen($words[$i])+1;
           if ($sum >= $length) $seg_line[] = $words[$i] . " ";
           else $pri_line[] = $words[$i] . " ";
       }
     
       for ($i = 0; $i < count($pri_line); $i++)
           $lines[0] .= $pri_line[$i];
         
       for ($i = 0; $i < count($seg_line); $i++)
           $lines[1] .= $seg_line[$i];
     
       return $lines;
   }
?>


ajd

Kyle's preserve_wordwrap is handy after fixing this error:
    $strs = explode($tstr,$br);
should be
    $strs = explode($br,$tstr);


info-at-oxyscripts-dot-com

Jeffrey Sambells code above has a few errors in it that prevented it working properly, which I have changed so that it works as desired. It will wrap a string properly, and exclude HTML from wrapping.
function even_better_wordwrap($str,$cols,$cut) {
$tag_open = '<';
$tag_close = '>';
$count = 0;
$in_tag = 0;
$str_len = strlen($str);
$segment_width = 0;
for ($i=0 ; $i<=$str_len ; $i++){
if ($str[$i] == $tag_open) {
$in_tag++;
} elseif ($str[$i] == $tag_close) {
if ($in_tag > 0) {
$in_tag--;
}
} else {
if ($in_tag == 0) {
$segment_width++;
if (($segment_width > $cols) && ($str[$i] != " ")) {
$str = substr($str,0,$i).$cut.substr($str,$i+1,$str_len-1);
$i += strlen($cut);
$str_len = strlen($str);
$segment_width = 0;
}
}
}
}
return $str;
}
Alex
http://www.oxyscripts.com


warwallace

It is also possible to consider this function as a tool for making text wrappable rather than simply for forcing wrapping.
In other words, use a space as the break - rather than "br /" or "p" or \n or whatever - and the text becomes wrappable.
$input = "I want to annoy you by inserting long wooooooooooooooooooooooooooooooooorrrrrrdddss into your guestbook.";
$output = wordwrap($input, 40, ' ', 1);
Will insert spaces into the words longer than 40 characters make the text wrappable by the browser.


25-aug-2002 08:40

Instead of using a space or a newline or <br /> as the line break separator, you may consider inserting  "Soft Hyphens" within the middle of long words, allowing elegant word breaking that can use the effective browser layout that is dependant of the effective font that the browser will use.
The "Soft Hyphen" (SHY) character is part of the STANDARD ISO-8859-1 character set: it won't be displayed (i.e. it will have width 0) if the two parts of a word can be displayed by the browser along on the same layout row. However it allows the browser to find a break in the middle of long words: in that case, it will display the first part of the word before the "Soft Hyphen", and a true Hyphen ("-") on the first layout row (if they both fit on that row), and the next part after the "Soft Hyphen" on the following layout row.
Ideally, each word should contain at least one "Soft Hyphen" between each syllable of a word, unless this would place a "Soft Hyphen" with less than 3 characters from the beginning or end of the word. So "Soft Hyphens" must not be inserted within words with 1 to 5 characters.
The Soft Hyphen is only appropriate within textual words using Latin, Greek, Cyrillic characters). For Semitic languages that use right to left scripts, the "Soft Hyphen" should be replaced by a "Soft Line Break" (also called "Zero Width Non Joiner" in Unicode).
This "Soft Line Break" always has a null display width (i.e. it is never displayed), except that it allows inserting a line break.
Some characters are already implicitly considered followed by a "Soft Line Break" in browsers: the explicit hyphen within composed words (like "week-end"), and all punctuations (with the exception of the dot, and opening punctuations like "({[" which are instead _preceded_ by an implicit "Soft Line Break").
Note also that some new browsers can insert themselves "Soft Hyphens" or "Soft Line Breaks" within long words, if the HTML page explicitly specifies the language, and the words are restricted to the natural characters of that language, using hyphenation rules and/or dictionnaries defined for that language.
Currently, the HTML standard offers no way to specify a set of hyphenation rules along with the page (so that it would work in absence of a known dictionnary for that language), so soft hyphens or line breaks should be placed in the content.


austinbarton

In response to some of the alternative wordwrap functions that attempt to work with HTML:
They do not work with anything that uses
or

to force breaks. This occurs as the replacement text does not match the original as it is not breaking up words appropriately.
The solution is to ignore formatting tags in the strip_tags function call ie:
strip_tags( $string, '
' );


rekcor

Improved version of egyptechno[at]gmail.com's wordCut.
In this improved function, the length of $sMessage is taken into consideration while cutting the text, so the returned string is never longer than $iMaxLength. Besides that, whole words are cut as well.
<?php
/**
* function wordCut($sText, $iMaxLength, $sMessage)
*
* + cuts an wordt after $iMaxLength characters
*
* @param  string   $sText       the text to cut
* @param  integer  $iMaxLength  the text's maximum length
* @param  string   $sMessage    piece of text which is added to the cut text, e.g. '...read more'
*
* @returns string
**/    
function wordCut($sText, $iMaxLength, $sMessage)
{
  if (strlen($sText) > $iMaxLength)
  {
      $sString = wordwrap($sText, ($iMaxLength-strlen($sMessage)), '[cut]', 1);
      $asExplodedString = explode('[cut]', $sString);
     
      echo $sCutText = $asExplodedString[0];
     
      $sReturn = $sCutText.$sMessage;
  }
  else
  {
      $sReturn = $sText;
  }
 
  return $sReturn;
}
?>


fatchris

If your string has some html entities, then it might split one in half. e.g.
<?php
/*
Outputs (Renders):
Préf&-
eacute;rence-
s e-mails
*/
echo wordwrap("Pr&eacute;f&eacute;rences e-mails");
?>
To solve this, you can use the following function:
<?php
function wordwrap2( $str, $width = 75, $break = '\n', $cut = true ) {
 $str = html_entity_decode( $str ); //first decode
 $out = wordwrap( $str, $width, $break, $cut ); //now wordwrap
 $out = htmlentities( $out ); //re-encode the entities
 $out = str_replace( htmlentities( $break ), $break, $out ); //put back the break
 return $out;
}
?>


timf

If you're having problems with a small fixed width table/table cell being stretched by people typing entering long text (such as a URL or an email address), then one (MSIE only, unfortunately) solution is to use style="table-layout:fixed" in the <table> tag.  This will break any words that would normally expand your table and mess up your layout.
wordwrap() can't help in this situation because you want to wrap if the text is wider than X pixels, rather than X characters, which of course PHP has know way of knowing.


dave lozier - dave

If you'd like to break long strings of text but avoid breaking html you may find this useful. It seems to be working for me, hope it works for you. Enjoy. :)
function textWrap($text) {
$new_text = '';
$text_1 = explode('>',$text);
$sizeof = sizeof($text_1);
for ($i=0; $i<$sizeof; ++$i) {
$text_2 = explode('<',$text_1[$i]);
if (!empty($text_2[0])) {
$new_text .= preg_replace('#([^\n\r .]{25})#i', '\\1  ', $text_2[0]);
}
if (!empty($text_2[1])) {
$new_text .= '<' . $text_2[1] . '>';
}
}
return $new_text;
}


jeff

If you want to skip HTML tags you could use something like this...
function better_wordwrap($str,$cols,$cut){
$tag_open = '<';
$tag_close = '>';
$count = 0;
$in_tag = 0;
$str_len = strlen($str);
$segment_width = 0;
 
for ($i=1 ; $i<=$str_len ; $i++){
if ($str[$i] == $tag_open) {
$in_tag++;
} elseif ($str[$i] == $tag_close) {
if ($in_tag > 0) {
$in_tag--;
}
} else {
if ($in_tag == 0) {
$segment_width++;
if (($segment_width > $cols) && ($str[$i] == " ")) {
 $str = substr($str,0,$i).$cut.substr($str,$i+1,$str_len-1);
 $i += strlen($cut);
 $str_len = strlen($str);
 $segment_width = 0;
}
}
}
}
return $str;
}
Jeffrey Sambells
http://www.wecreate.ca


krang

If you are trying to make something like a forum, and you have considered that people my put in LONG words so that the table is stretched out of proportion.
Word wrap will work, but doesn’t really do the job intended. With a text box named NEW_MESSAGE submitting the message, this is a possible way to get round it...
// Instance of new line (\r\n) with < br >
// Note, the received string from a text
// area may use different methods of
// symbolising the new line
   $NEW_MESSAGE = str_replace("\r\n", " < br > ", $NEW_MESSAGE);
// Split it into the different words, if
// there to long word add a space then
// put all the words back into a new variable.
$SPLIT_NEW_MESSAGE = explode(" ", "$NEW_MESSAGE");
$NUMBER_OF_ELEMENTS = count($SPLIT_NEW_MESSAGE);
$COUNT = 0;
     // Loop though all the words, if one is longer than
     // 40 characters put in a space, then add this word
     // to the variable containing the processed string
while ($COUNT <= $NUMBER_OF_ELEMENTS) {
   $CURRENT_WORD = $SPLIT_NEW_MESSAGE[$COUNT];
   $LENGTH_OF_WORD = strlen ($CURRENT_WORD);
   if ($LENGTH_OF_WORD >= 40) {
$CURRENT_WORD = wordwrap( $CURRENT_WORD, 40, " ", 1);
   }
   $FINAL_NEW_MESSAGE .= "$CURRENT_WORD ";
   $COUNT = $COUNT + 1;
}
// Now print out the finished string – you might want to
// store it in a database or do some other work to it.
Echo “$FINAL_NEW_MESSAGE”;


ekgerke

If the last line of string does not end with newline character, wordwrap tends to add trailing garbage.

19-jul-2006 05:47

I've written another implemention of textwrap, becourse the last one didnt work for me.
<?php
function textwrap ($text, $length, $break) {
$pure=strip_tags($text);
$words=str_word_count($pure, 1);
foreach ($words as $word) {
if (strlen($word) > $length) {
$newword=wordwrap($word, $length, $break, TRUE);
$text=str_replace($word, $newword, $text);
}
}
return $text;
}
?>


toxic79_spam

I've noticed that if you have a string of, say, 8 characters and you set it to wrap at 8 characters with a break tag it will add the break tag after the 8th character even if the string is only 8 characters long. this was frustrating because I only wanted the break tag if there would be more text after it. it would be cool to have a flag that would stop this from happening, or a flag that would put the break tag (or whatever you use) before the number you break on, so you could set it to break every 9th character and it would only insert the tag after the 8th if there are more than 8 characters.
until then, however, here is my lame fix. $str is the string to wrap, $num is the number of characters to wrap after and $break is the text to use to wrap the string.
function my_wordwrap( $str, $num, $break )
{
// get the wordwrapped string
$tmp_str = wordwrap( trim( $str ), $num, $break, 1 );
// get the string length of the breaking tag
$strlen_break = strlen( $break );
// if the last $strlen_break characters of the wordwrapped string is $break ...
if ( substr( $tmp_str, ( 0 - $strlen_break )) == $break )
{
// strip the last $strlen_break characters off the end
$tmp_str = substr( $tmp_str, 0, count( $tmp_str ) - $strlen_break - 1 );
}

// return the results
return $tmp_str;
}


matt

I've extended one of the examples above so it does wrap "words" longer than a specific limit but will (in most cases) not touch any URLs since you may allow links in your messageboard/guestbook:
$message = ereg_replace("([^ \/]{32})","\\1<wbr>",$message);
Note that the slash will usually prevent URLs from being messed up if no single segment is longer than the given limit.


tylernt

I wrote this to keep long strings from making my tables wider than the browser window. To lessen the impact on performance, only call this function on strings longer than 'X' characters.
// This function will insert the 'wbr' (optional linebreak) tag
// to wrap words in $string longer than 10 characters,
// but will not break inside HTML tags
function mywordwrap($string)
{
$length = strlen($string);
for ($i=0; $i<=$length; $i=$i+1)
{
$char = substr($string, $i, 1);
if ($char == "<")
$skip=1;
elseif ($char == ">")
$skip=0;
elseif ($char == " ")
$wrap=0;
if ($skip==0)
$wrap=$wrap+1;
$returnvar = $returnvar . $char;
if ($wrap>9) // alter this number to set the maximum word length
{
$returnvar = $returnvar . "<wbr>";
$wrap=0;
}
}
return $returnvar;
}


luismorrison

i wrote this by mistake because i didn't know that the same function already exists in PHP.. well shit happens, its quite simple but maybe this will help you someday in your project. The difference is that the one i wrote, called 'splitstroverflow()', cuts given string and parses into arrays to do whatever you like with them.
<?php
function splitstroverflow($cadena,$longitud) {
$pri_renglon = array();
$seg_renglon = array();
$palabras = explode(" ",trim($cadena));

for ($i = 0; $i < count($palabras); $i++) {
$sum += strlen($palabras[$i])+1;
if ($sum >= $longitud) $seg_renglon[] = $palabras[$i] . " ";
else $pri_renglon[] = $palabras[$i] . " ";
}

for ($i = 0; $i < count($pri_renglon); $i++)
$renglones[0] .= $pri_renglon[$i];

for ($i = 0; $i < count($seg_renglon); $i++)
$renglones[1] .= $seg_renglon[$i];

return $renglones;
}
?>
Usage:
<?php
splitstroverflow(str longString,int lenght);
$myrow = splitstroverflow("This is my long long long string",18);
// the array counts 2 elements
// Array
// (
// [0] => "This is my long"
// [1] => "long long string"
// )
?>


pawan

I wanted to use this function to add a particular text after a certain word count. Here is how I implemented it:
$content = wordwrap($content, 200, "....<br /><!--more-->\n");
Above code adds the text '...<br/><!--more-->\n' after a 200 word count. I know there are a million ways this can be done in PHP. Go PHP!


23-may-2002 11:29

I use this for word-wrapping. It brakes up long words (wich are not real words, since often these long, table breaking, texts are URLs or evil text ment to make the tables look bad). I have some problems with URLs, since it will just simply put a
tag in it, etc. But for the most part it works perfectly; since few people ever write words beyond 42 characters, and all otherwords are managed within the table by the webbrowser.
$message = ereg_replace("([^ ]{42})","\\1
",$message);


subzane

I use preg_replace instead...
This function doesn't cut in HTML tags, just in the plain text.
<?php
function WrapWords($str, $chars) {
 $str = preg_replace('/([^\s\<\>]{'.$chars.','.$chars.'})/', '\1 ', $str);
 return $str;
}
?>


radaway

I noticed you guys better wordwrap was erasing some characters so I changed it, namely the line:
substr($str,0,$i-1).$cut.substr($str,$i,$str_len-1);
Hope its of some use.
function even_better_better_wordwrap($str,$cols,$cut) {
  $tag_open = '<';
  $tag_close = '>';
  $count = 0;
  $in_tag = 0;
  $str_len = strlen($str);
  $segment_width = 0;
  for ($i=0 ; $i<=$str_len ; $i++){
      if ($str[$i] == $tag_open) {
  //tamos dentro de uma tag html
          $in_tag++;
          } elseif ($str[$i] == $tag_close) {
      //fechamos uma tag html
              if ($in_tag > 0)
                  $in_tag--;
          } else {
              if ($in_tag == 0) {
  //se nao estamos dentro de uma tag html
                  $segment_width++;
                  if (($segment_width > $cols) && ($str[$i] != " ")) {
      //se passamos o limite de colunas acrescentamos o $cut no sitio
                      $str = substr($str,0,$i-1).$cut.substr($str,$i,$str_len-1);
                      $i += strlen($cut);
                      $str_len = strlen($str);
                      $segment_width = 0;
                  }
              }
          }
  }
  return $str;
}


edward

I needed a function to justify the text - not just wrap it. I came up with this:
<?
function justify($text, $width, $break) {
       $marker = "__$%@random#$()__";
       // lines is an array of lines containing the word-wrapped text
       $wrapped = wordwrap($text, $width, $marker);
       $lines = explode($marker, $wrapped);
       
       $result = "";
       foreach ($lines as $line_index=>$line) {
               $line = trim($line);
               
               $words = explode(" ", $line);
               $words = array_map("trim", $words);
               $wordcount = count($words);
               $wordlength = strlen(implode("", $words));
               
               if (3*$wordlength < 2*$width) {
                       // don't touch lines shorter than 2/3 * width
                       continue;
               }
               
               $spaces = $width - $wordlength;
               
               $index = 0;
               do {
                       $words[$index] = $words[$index] . " ";
                       $index = ($index + 1) % ($wordcount - 1);
                       $spaces--;
               } while ($spaces>0);
               
               $lines[$line_index] = implode("", $words);
       }
       
       return implode($break, $lines);
}
?>


engrkhalid

I found this function helpful to cut long words without adding spaces:
function fWrap ( $vText, $vMax ) {
$vWords = explode(" ", $vText);
foreach ( $vWords as $i =>$w ) {
if ( strlen ( $vWords[$i] ) > $vMax ) { $vWords[$i] = wordwrap( $vWords[$i], $vMax, "<wbr>", 1 ); }
}
return implode(" ", $vWords);
}
Regards.


bruceboughton @ google mail

I found that wordwrap deletes the spaces it wraps on. If you want to break up a string which doesn't consist of words, you may find this behaviour undesirable, as I did when trying to wordwrap a Regular Expression to 80 characters (for display along with test string, matches, etc.).
To preserve the spaces and still achieve a consistent cut length, you need to replace spaces with a suitable one-character replacement. I chose the ASCII non-printing character SUB (ASCII #26; some old telephone code meaning substitute):
<?php
$regex= str_replace(' ', chr(26), $regex);
$regex= wordwrap($regex, 80, '<br />', TRUE);
$regex= str_replace(chr(26), ' ', $regex);
?>
(Of course, you need to replace 80 with your column length and '<br />' with your break string)


philippe %a% niquille dot com

I changed the wordsplit function a bit, so that it returns an array containing all the text chunks, not only the cutted one:
<?
function _split_text($text)
{
$MAX_LENGTH = 160;
 $split=explode(" ",$text);
 $numwords = count($split);
 $i=0; //while counter
 $a = 1; //counts the text chunks
 $amount = ceil(strlen($text)/($MAX_LENGTH-5)); //get total word chunks
 while($i < $numwords){
   $len = (strlen($newtext[$a])+strlen($split[$i])); //get length of the active chunk
     if($len>($MAX_LENGTH-5)){ //do we have to start a new one?
       $a++;
       $newtext[$a] = "[$a/$amount] "; //Adds [1/2]
     }else{
       if($i == 0) $newtext[$a] = "[$a/$amount] ";
       $newtext[$a]=$newtext[$a]." ".$split[$i];
       $i++;
     }
 }
 return $newtext;
}
}
?>
I used the function for a sms sending script to automatically cut the user's message.


paolo stefan

Hi everyone,
I have modified textWrap(); this one works just fine (the last one had a buggy regular expression!) and also gives you the chance to choose the line separator (3rd param).
Enjoy :)
<?php
function textWrap($text, $size, $separator="\\r\\n" ) {
$new_text = '';
$text_1 = explode('>',$text);
$sizeof = sizeof($text_1);
$remain = $size;

for ($i=0; $i<$sizeof; ++$i) {
 
  $text_2 = explode('<',$text_1[$i]);
 
  if (!empty($text_2[0])){
  $perl = '/([^\\n\\r .]{'. $remain .',})/i';
$possibly_splitted= preg_replace( $perl, '$1'.$separator, $text_2[0] );

$splitted = explode($separator,$possibly_splitted);
$remain -= strlen($splitted[0]);
if($remain<=0) $remain = $size;

  $new_text .= $possibly_splitted;
  }

  if (!empty($text_2[1])) $new_text .= '<' . $text_2[1] . '>';
}
return $new_text;
}
?>


shaun

Here's some code which will turn text into a quoted message, that is, split a chunk of text into wrapped lines and prefix each line of text with a > sign (or some other delimiter). I found myself using this snippet so many times while writing an autoresponder that I just dropped it into a function.
function mailquote($text, $marker){
 $text = str_replace("\n", "\n$marker", wordwrap($text, 70));
 return $text;
}
e.g.
mailquote($text, "> ");
> Would result in a long passage of text
> being broken into multiple lines, each
> line starting with a traditional "quote"
> marker, like this.


webmaster

Here's one I've being using, feel free to give it a go...
function WrapText($String = "", $BreakAt = 70, $BreakWith = "<br />\n"){
return preg_replace("#([^\s\"'/\.\\-\?&\n\%<>]{". $BreakAt ."})#i"," {$BreakWith}",$String);
}
Function Parameters In Order:
1st - String
2nd - Break Text After X Characters (Default 70)
3rd - Break Insertion (Default <br />\n)


grey - greywyvern - com

Here's an HTML wrapping + nl2br function I developed.  It inserts line-breaks into long strings of characters in HTML-formatted text while ignoring tags and entities.  It also counts each entity as a single character, and only applies nl2br to text nodes.  You can also tell it to ignore whole elements, like <pre> where adding <br /> isn't necessary.  
Great for formatting HTML generated by user input.  I distribute simple forum and blog scripts where codes input by the user are translated to HTML.  I send the result through this function to format it correctly and make sure they don't maliciously type in long words in order to break my layout.
http://www.greywyvern.com/code/php/htmlwrap_1.0.php.txt


mzajonc

Here is another function for soft-hypens.  It could also be used with spaces which is actually probably a reasonable idea since ­ is not universally supported (ie netscape through 6.2 doesn't handle it).
<?php
/**
* soft_hypen() inserts soft hyphens (or user defined) in words that exceed certain length.
*
* @param $text Text to hyphenate.
* @param $max Max word size.
* @param $char Hyphenate character.  Defaults to HTML soft hyphen ­.
* @return The text with inserted soft hyphens.
**/
function soft_hyphen($text, $max, $char = "­")
{
$words = explode(' ', $text);
foreach($words as $key => $word)
{
$length = strlen($word);
if($length > $max)
$word = chunk_split($word, floor($length/ceil($length/$max)), $char);
$words[$key] = $word;
}
return implode(' ', $words);
}
?>


feedback

Here is a way to use wordwrap to add spaces to long "words", without breaking link tags -- I came up with this as there apparently is no way to reproduce this effect with a regular expression.
This is mostly used in users-posts where your output layout could be broken with words that are longer than what the container object can take - it will not effect html tags (such as <a href="aaaaaaaaaaaaaaaaaaaaaaaaa"> so you don't end up with broken links !
$body = 'this is a text with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa looooooooooooooooooooooooooooong word! <a href="http://ww.this.site.com/with/a/loooooooooooooooooooooong/url'> ... </a>';
foreach(explode(" ", strip_tags($body)) as $key => $line) {
 if (strlen($line) > 35) $body = str_replace($line, wordwrap($line, 25, " ", 1), $body);
}
(In case you would like the same thing without the tags protection, there is a regular expression way;
$body = preg_replace("/([^\s]{35})/","$1 ",$body);


lorang

Hello,
If you nee a function that limits a text to a certain number of characters, but it should always keep the whole words, try this :
function limit_text($text,$maxchar){
$split=explode(" ",$text);
$i=0;
while(TRUE){
$len=(strlen($newtext)+strlen($split[$i]));
if($len>$maxchar){
break;
}else{
$newtext=$newtext." ".$split[$i];
$i++;
}
}
return $newtext;
}


buganini

function strwidth($s){
/*
put some fix for ambiguous width hese
*/
               $ret = mb_strwidth($s, 'UTF-8');
               return $ret;
       }
       function mb_wordwrap($str, $wid, $tag){
               $pos = 0;
               $tok = array();
               $l = mb_strlen($str, 'UTF-8');
               if($l == 0){
                       return '';
               }
               $flag = false;
               $tok[0] = mb_substr($str, 0, 1, 'UTF-8');
               for($i = 1 ; $i < $l ; ++$i){
                       $c = mb_substr($str, $i, 1, 'UTF-8');
                       if(!preg_match('/[a-z\'\"]/i',$c)){
                               ++$pos;
                               $flag = true;
                       }elseif($flag){
                               ++$pos;
                               $flag = false;
                       }
                       $tok[$pos] .= $c;
               }
               $linewidth = 0;
               $pos = 0;
               $ret = array();
               $l = count($tok);
               for($i = 0 ; $i < $l ; ++$i){
                       if($linewidth + ($w = strwidth($tok[$i])) > $wid){
                               ++$pos;
                               $linewidth = 0;
                       }
                       $ret[$pos] .= $tok[$i];
                       $linewidth += $w;
               }
               return implode($tag, $ret);
       }


hokus_123

for ex. msgbrds where HTML hyberlinks occur, wrapping words will devide long URLs and make them invalid. Here is a "real" wordwrap that does not break up HTML hyberlinks.
<?PHP
function mywordwrap($str, $max = 75, $break = ' ') {
 
 // create array by deviding at each occurrence of "<a"
 $arr = explode('<a', $str);
 // break up long words in $arr[0] since
 // it will never contain a hyberlink
 $arr[0] = preg_replace('/([^\s]{'.$max.'})/i',"$1$break",$arr[0]);
 // run loop to devide remaining elements
 for($i = 1; $i < count($arr); $i++) {
   // devide each element in $arr at each occurrence of "</a>"
   $arr2 = explode('</a>', $arr[$i]);
   // break up long words in $arr2 that does not
   // contain hyberlinks
   $arr2[1] = preg_replace('/([^\s]{'.$max.'})/i',"$1$break",$arr2[1]);
   // rejoin $arr2 and assign as element in $arr
   $arr[$i] = join('</a>', $arr2);
 }
 // rejoin $arr to string and return it
 return join('<a', $arr);
}
?>


andrej dot pavlovic

Disregard my note from below, since the function only works for utf8 strings that can be encoded into ISO-8859-1.

egyptechno

Another function to cut text afterr $limit letters ,
function :
function wordCut($text, $limit, $msg){
if (strlen($text) > $limit){
$txt1 = wordwrap($text, $limit, '[cut]');
$txt2 = explode('[cut]', $txt1);
$ourTxt = $txt2[0];
$finalTxt = $ourTxt.$msg;
}else{
$finalTxt = $text;
}
return $finalTxt;
}
return :
The limited text
description :
It takes the text, add the string '[cut]' every $limit text by wordwrap, then we explode the text with '[cut]' and takes the first element in the array which we need !
how to use :
wordCut($my_text, 200, '... read more');
EgypTechno


thr

An updated function to wrap normal words - and not chars, this will be much faster then the other ones posted previously:
function real_wordwrap($string,$width,$break)
{
$string = preg_replace('/([^\s]{'.$width.'})/i',"$1$break",$string);
return $string;
}


php

A fix for wordwrap() is available here :
http://www.42-networks.com/php/wordwrap.patch
The native function will then properly cut words after non-alphanumeric characters, not only after a plain space.


golanzakaiatpatterndotcodotil

/**
    * Wordwrap without unnecessary word splitting using multibyte string functions
    *
    * @param string $str
    * @param int $width
    * @param string $break
    * @return string
    * @author Golan Zakai <golanzakaiATpatternDOTcoDOTil>
    */
   function _wordwrap( $str, $width, $break ) {
       $formatted = '';
       $position = -1;
       $prev_position = 0;
       $last_line = -1;
       
       /// looping the string stop at each space
       while( $position = mb_stripos( $str, " ", ++$position, 'utf-8' ) ) {
           if( $position > $last_line + $width + 1 ) {
               $formatted.= mb_substr( $str, $last_line + 1, $prev_position - $last_line - 1, 'utf-8' ).$break;
               $last_line = $prev_position;
           }
           $prev_position = $position;
       }
       
       /// adding last line without the break
       $formatted.= mb_substr( $str, $last_line + 1, mb_strlen( $str ), 'utf-8' );
       return $formatted;
   }


anthony catel paraboul

<?php
function cut_word($txt, $where) {
if (empty($txt)) return false;
for ($c = 0, $a = 0, $g = 0; $c<strlen($txt); $c++) {
   $d[$c+$g]=$txt[$c];
   if ($txt[$c]!=" ") $a++;
   else if ($txt[$c]==" ") $a = 0;
   if ($a==$where) {
$g++;
$d[$c+$g]="<br />";
$a = 0;
   }
}
return implode("", $d);
}
?>
Wrap word for cut only long word :
<?
cut_word($sentence, 25);
?>


phpsales

########################################
# Break long words with out cutting HTML tags.
########################################
/* Break Long Words (string, int, char) */
function breakLongWords($str, $maxLength, $char){
$wordEndChars = array(" ", "\n", "\r", "\f", "\v", "\0");
$count = 0;
$newStr = "";
$openTag = false;
for($i=0; $i<strlen($str); $i++){
$newStr .= $str{$i};

if($str{$i} == "<"){
$openTag = true;
continue;
}
if(($openTag) && ($str{$i} == ">")){
$openTag = false;
continue;
}

if(!$openTag){
if(!in_array($str{$i}, $wordEndChars)){//If not word ending char
$count++;
if($count==$maxLength){//if current word max length is reached
$newStr .= $char;//insert word break char
$count = 0;
}
}else{//Else char is word ending, reset word char count
$count = 0;
}
}

}//End for
return $newStr;
}


Change Language


Follow Navioo On Twitter
addcslashes
addslashes
bin2hex
chop
chr
chunk_split
convert_cyr_string
convert_uudecode
convert_uuencode
count_chars
crc32
crypt
echo
explode
fprintf
get_html_translation_table
hebrev
hebrevc
html_entity_decode
htmlentities
htmlspecialchars_decode
htmlspecialchars
implode
join
levenshtein
localeconv
ltrim
md5_file
md5
metaphone
money_format
nl_langinfo
nl2br
number_format
ord
parse_str
print
printf
quoted_printable_decode
quotemeta
rtrim
setlocale
sha1_file
sha1
similar_text
soundex
sprintf
sscanf
str_getcsv
str_ireplace
str_pad
str_repeat
str_replace
str_rot13
str_shuffle
str_split
str_word_count
strcasecmp
strchr
strcmp
strcoll
strcspn
strip_tags
stripcslashes
stripos
stripslashes
stristr
strlen
strnatcasecmp
strnatcmp
strncasecmp
strncmp
strpbrk
strpos
strrchr
strrev
strripos
strrpos
strspn
strstr
strtok
strtolower
strtoupper
strtr
substr_compare
substr_count
substr_replace
substr
trim
ucfirst
ucwords
vfprintf
vprintf
vsprintf
wordwrap
eXTReMe Tracker