|
wordwrap
Wraps a string to a given number of characters
(PHP 4 >= 4.0.2, PHP 5)
Example 2485. wordwrap() example<?php The above example will output: The quick brown fox<br /> Example 2486. wordwrap() example<?php The above example will output: A very Code Examples / Notes » wordwrapkyle
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éfé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 doesnt 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 Languageaddcslashes 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 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 |