Am I misunderstanding strlen()? - php

I'm trying to properly understand strlen() in PHP to make a application where text is shortened and finished with a ...
My code:
$prize_text = "Learn how to eat pizza TODAY";
if (strlen($prize_text) > 24) {
$prize_text = substr($prize_text, 0, 21) . '...';
}
$prize_text = "Watch Good Day Sunshine Today!";
$prize_text = "abcdefghijklmnopqrstuvwxyz";
Why is everything not matching up? I want one uniform standard of shortening the text and then appending three dots. What is wrong with my code?

Wrong tool for the job. You want CSS instead to avoid the breaking problem you're having.
#element {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
Advantages
You can hide/show the text at will, whereas with PHP the text sent is already rendered in the document.
Will work for multiple situations whereas the PHP is hard-coded.

strlen() count the number of characters in string not space occupied by the string on viewport. You can make same length by make all characters in samecase- either in lowercase or uppercase, to make all string with same width you may take reference of http://www.ampsoft.net/webdesign-l/WindowsMacFonts.html

Related

PHP closing tag deletes the line feed

I'm doing an experiment, an html preprocessor like SLIM or Jade.
This is the PHP code that seems right:
nav
ul id: "test"
li
#<?= $Var; ?>
li
#About
li
#Contact
This is the expected pre-processed html (yes, $Var == "Test"):
nav
ul id: "test"
li
#Test
li
#About
li
#Contact
However, in the browser I get this wrong text as the pre-processor html:
nav
ul id: "test"
li
#Test li
#About
li
#Contact
Lastly, there are two ways to make it correct.
Adding the break line manually:
nav
ul id: "test"
li
#<?= $Var . "\n"; ?>
li
#About
li
#Contact
Writing a space after the PHP closing tag (??).
Why is the first case, <?= $Var; ?>, ignoring the line feed after the closing PHP tag? I couldn't really find anything since google brought too many results about why you should ignore the closing tag for every search I did and not what I wanted to find.
Update:
Looking at the zend language scanner src, it would seem that my "hunch" was correct: the T_CLOSE_TAG token would appear to possibly contain a newline char. What's more, It'd also seem that a closing semi-colon for the last statement in a script that contains a closing tag is optional...
<ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"){NEWLINE}? {
ZVAL_STRINGL(zendlval, yytext, yyleng, 0); /* no copying - intentional */
BEGIN(INITIAL);
return T_CLOSE_TAG; /* implicit ';' at php-end tag */
}
Just look for T_CLOSE_TAG in the zend_language_scanner.c and zend_language_scanner.l files here
I'm currently scanning the source of the Zend engine, to be sure, but I'd guess that, since the last char(s) of the code you posted are, simply, the closing tag (?>), it's PHP that is generating the output. Seeing as you're not telling PHP to output a line-feed, it stands to reason that PHP won't add a new line to whatever you're echoing.
The line-feed char that follows the closing tag is, of course, ignored by PHP, but for some reason, PHP does indeed seem to consume that line feed. I'm looking at the C code that parses your PHP script, but I'm thinking it might use new-lines, whitespace, comma's semi-colons and all that as tokens to chunk the input into nodes.
Seeing as the closing tag ?> is a bona-fide token, and part of the PHP grammar, It could well be that this is where the line-feed is effectively consumed by the engine, and why it's not part of the output.
By adding a space char after the closing tag, The space might be consumed, but the new-line isn't, so that might be why you're still seeing the line-feed show up.
I've also tried adding 2 line feeds to some test code, and indeed: the output showed only 1 new line:
foo:
<?= $bar; ?>
foobar
Output:
foo:
bar
foobar
So it would seem that my suspicions might hold water.
However, all things considered, lest you want to go hacking away at the Zend engine source, adding the line-feed manually isn't that much of a hasstle. In fact, it's a good way to ensure the correct line-feeds are generated:
Suppose you wrote some code, on a healty *NIX system, where line-feeds are, to all intents and purposes represented by the \n escape sequence, adding that char manually might not yield the desired output on, say, a windows system (which uses \r\n), Apple systems use \r...
PHP has a constant to ensure you're churning out the correct line-feeds, depending on the platform your code is running on: PHP_EOL. Why not use that:
<?= $bar, PHP_EOL; ?>
In case you're wondering: yes, that is $bar comma PHP_EOL you're seeing there. Why? Think of echo or <?= as C++'s COUT, it's a construct that just pushes whatever you're throwing at it to the output stream, weather it be a concatenated string, or just a comma separated list of variables: it doesn't care.
Now, the following section of my answer is going slightly off-topic, but it's just something so basic, and self-evident, and yet many people are so un-aware of it, that I can't resist the temptation of explaining a thing or two about string concatenation.
PHP, and most any language I know of, doesn't care about how many vars/vals it has to push to the output stream. It's what it's for. PHP, and again: most languages, does care about concatenation of strings: A string is sort of a constant value. You can't just make a string longer when the mood takes you. A series of chars have to be stored in memory, memory that has to be allocated to accommodate a longer string. What concatenation effectively does (best case scenario), is this:
compute length of string1 and string2
allocate additional memory required to concat string2 onto string 1
copy string 2 to that newly (extra) allocated memory
Whereas, in a lot of cases, what actually happens is:
compute lengths of both strings
allocate memory, required to concat both strings
copy both strings to that newly allocated memory block
assign the new pointer to whatever variable needs assigning
free up any memory that isn't referenced anymore
An example of the first case:
$str1 = 'I am string constant 1';
$str2 = ' And I\'ll be concatenated';
$str1 .= $str2;
Could translate to the following C code:
char *str1, *str2;
//allocate mem for both strings, assign them their vals
str1 = realloc(str1,(strlen(str1) + strlen(str2)+1));//re-allocate mem for str1
strncat(str1, str2, strlen(str2);//concatenate str2 onto str1
However, by simply doing this:
$str3 = $str1 . $str2;
What you're actually doing is:
char *str3 = malloc((strlen(str1) + strlen(str2) + 1)*sizeof(char));
strcpy(str3, str1);//copy first string to newly allocated memory
strcat(str3, str2);//concatenate second string...
And as if that weren't enough, just think what this code implies:
$str1 = $str2 . $str1;
Yes, sure enough:
char *str3 = malloc((strlen(str1) + strlen(str2) + 1)*sizeof(char));
strcpy(str3, str2);//copy seconds string to start of new string
strcat(str3, str1);//add first string at the end
free(str1);//free memory associated with first string, because we're reassigning it
str1 = str3;//set str1 to point to the new block of memory
Now I haven't even gotten to the real concatenation nightmares yet (don't worry, I'm not going to either). Stuff like $foo = 'I ' . ' am '. 'The'. ' ' .$result.' of some'.1.' with a dot'.' fetish';. Look at it, there's variables in there, that might be anything (arrays, objects, huuuge strings..., there's an integer in there, too... replace the dots with comma's and pushing it to the echo construct just is so much easier than even begin contemplating writing the code required to correctly concatenate all of these values together...
Sorry for drifting off here slightly, but seeing as this is, IMO, so basic, I feel as though everyone should be aware of this...

Html2pdf doesn't support word-break:break-all css

hai everybody i am using html2pdf ,it doesn't support word-break:break-all css any idea?
example
<td style="width:30%;word-break:break-all ;">
testtestetstetstetstetstettstetstetstetstetstetstetstetstetstetstets
</td>
output pdf take above 30% width like string length size
output pdf: testtestetstetstetstetstettstetstetstetstetstetstetstetstetstetstets
I want Output :
testtestetstetstetstetstettstets tetstetstetstetstetstetstetstets
Well, that's complicated. Your teststring is too long, but it's not composed of multiple words. That means that word-break won't work, because there aren't any words to break on. Obviously, this might well just be an example, in which case it might be that html2pdf just doesn't support relative widths and word-break, so you could try having an absolute width and word-break.
That said, here's something I know that will work: wordwrap in PHP. So, instead of echo $yourvar; you could use echo wordwrap($yourvar, 75, "\n", true) instead, which will always cut the string, even if it's just one long string. It takes a little fiddling to get the number of characters to match up with the width that you're looking for, but it will work.
<?php
$foo = str_repeat('test',12);
echo wordwrap($foo, 20, '<br />', true);
Output:
testtesttesttesttest
testtesttesttesttest
testtest
try this;
<td style="width:30%; word-wrap:break-word;">
testtestetstetstetstetstettstetstetstetstetstetstetstetstetstetstets
</td>
not word-break it is word-wrap ;
If you want long strings to wrap consistently within a boundary container I think you should be able to accomplish this by inserting zero-width space characters (​ or \xe2\x80\x8b) between every letter of the orignial string. This will have the effect of wrapping as if every character was its own word, but without displaying the spaces to the end user. This may cause you trouble with text searches or indexing on the final product, but it should accomplish the task reliably from an aesthetic perspective.
Thus:
testtestetstetstetstetstettstetstetstetstetstetstetstetstetstetstets
Becomes
t​e​s​t​t​e​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s
(which displays: "t​e​s​t​t​e​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s​t​e​t​s")
So if you wrap it it will wrap exactly to the bounds of its container. Here's a fiddle of it as an example.
Just write a PHP script to loop though the string and insert the space:
$string="testtestetstetstetstetstettstetstetstetstetstetstetstetstetstetstets";
$new_string = "";
for($i=0;$i<strlen($string);$i++){
if ($string[$i]==' ' || $string[$i+1]==' '){ //if it is a space or the next letter is a space, there's no reason to add a break character
continue;
}
$new_string .= $string[$i]."​";
}
echo $new_string
This is a particularly nice solution, because unlike wordwrap(), it automatically adjusts for non-fixed-width fonts (which is basically 99% of fonts that are actually used).
Again, if you need to resulting PDF to be searchable, this is not a good approach, but it will make it look like you want it to.
In your testing the word break will not work because the word break only works between the words in a particular sentence. So yo can use the multiple word sentence and then try with the word breaker
You just use substr function in your code.
I put a example for this. First put your output in variable.
$get_value = "testtestetstetstetstetstettstetstetstet";
$first = substr("$get_value",0,3);
$second = substr("$get_value",4,7);
and so on.
You can use "\r\n" to print newline character. make sure to use it with double quote. If your string is in the variable then you need to use word count function and append this string. You can also use PHP_EOL to avoid platform dependency.
html2pdf does not support this word-break:break-all css
Ref: http://www.yaronet.com/en/posts.php?sl=&h=0&s=151321#0
You may use this method.
<?php
$get_value = "testtestetstetstetstetstettstetstetstet";
$first = substr("$get_value",0,3);
$second = substr("$get_value",4,7);
$third = substr("$get_value",8,11);
?>
I want to add little bit of own experience with HTML2PDF and tables.
I used this solution to generate the PDF containing a table filled with delivery confirmation (list of products). Such list may contain up to thousand of products (rows).
I encountered a problem with formatting and long strings in cells. First problem was that the table was getting too wide even if I set the table's width to 100% and the width of header (<th>) columns (HTML2PDF does not support <colgroup> so I couldn't define it globally) - some columns were out of visible area. I used wordwrap() with <br /> as separator to break down the long strings which looked like it's working. Unfortunately, it turned out that if there is such long string in first and last row the whole table is prepended and appended with empty page. Not a real bugger but doesn't look nice either. The final solution was to (applies for tables which width could outreach the visible area):
set the fixed widths of table and each row in pixels
for A4 letter size I am using total width of 550 px with default margins but you'd have to play around a little to distribute the width between columns
in wordwrap use empty space or ​ / \xe2\x80\x8b as delimiter
For small tables that you'd like to spread for 100% of visible area width it is OK to use width expressed in %.
I think this function is a limping solution.
function String2PDFString($string,$Length)
{
$Arry=explode(" ",$string);
foreach($Arry as $Line)
{
if(strlen($Line)>$Length)
$NewString.=wordwrap ($Line,$Length," ",true);
else
$NewString.=" ".$Line;
}
return $NewString;
}

Add space before a numbers in PHP

How can I add space before numbers in PHP, to get output like the following?
 9  
10
100
I'm using str_pad($k,3,'',STR_PAD_LEFT), but blank space is not working. And I don't want leading zeros, but I want blank spaces.
You may be looking for str_pad().
foreach (array(1,2,3,100,1000) as $number)
echo str_pad($number, 10, " ", STR_PAD_LEFT);
However, if you want to output this in HTML, the multiple spaces will be converted to one. In that case, use as the third parameter.
Also, if you use a font like Times or Arial, this will never produce perfectly exact results, because characters differ in width. For perfect results, you need to use a Monospace font like Courier.
Anyway, check #Mark Baker's answer first. Right aligning the data using CSS's text-align: right is the best solution in most cases.
If you're displaying the result in a web browser, then you should be aware that browsers have this nasty little tendency to convert multiple white spaces to a single space. To check if your code is working, use the browser's "view source" option and count the spaces in the actual source rather than the rendered display.
Then look at alternatives such as or right-aligning your values using CSS.
When printing the numbers:
printf("%5d\n", $number);
Replace the 5 with how many spaces width minimum you want.
Use the function str_pad for this purpose.
This is what you are looking for:
str_replace(" "," ",str_pad($number, 5,' ', STR_PAD_LEFT));
grml, look into my comment. I don't know why here the nbsp :) is gone

shorten a word in a block of text

I have a block of text which occasionally has a really long word/web address which breaks out of my site's layout.
What is the best way to go through this block of text and shorten the words?
EXAMPLE:
this is some text and this a long word appears like this
fkdfjdksodifjdisosdidjsosdifosdfiosdfoisjdfoijsdfoijsdfoijsdfoijsdfoijsdfoisjdfoisdjfoisdfjosdifjosdifjosdifjosdifjosdifjsodifjosdifjosidjfosdifjsdoiofsij and i need that to either wrap in ALL browsers or trim the word.
You need wordwrap function i suppose.
You could truncate the string so it appears with an ellipsis in the middle or the end of the string. However, this would be independent from the actual rendering in a webbrowser. There is no way for PHP to determine the actual length a string will have with a certain font when rendered in a browser, especially if you have defined fallback fonts and don't know which font is used in the browser, e.g.
font-family: Verdana, Arial, sans-serif;
Compare the following:
I am 23 characters long
I am 23 characters long
Both chars have the same length, but since the one is monotyped and the other isn't the actual width it will have is different. PHP cannot determine this. You'd have to find a client side technology, probably JavaScript, to solve this for you.
You could also wrap the text into an element with the CSS property overflow:hidden to make the text disappear after a fixed length.
Look around SO. I'm pretty sure this was asked more than once before.
You could use the word-wrap: break-word CSS property to wrap the text that breaks your layout.
Check out the Mozilla Developer Center examples which demonstrate its use.
function fixlongwords($string) {
$exploded = explode(' ', $string);
$result = '';
foreach($exploded as $curr) {
if(strlen($curr) > 20) {
$curr = wordwrap($curr, 20, '<br/>\n');
}
$result .= $curr.' ';
}
return $result;
}
This should do the job.
You could do something like this:
preg_replace("/(\\S{20})/", '$1‌', $text);
It should* add a zero-width non-join character into all words each 20 characters. This means they will word-wrap.
* (untested)
Based on #JonnyLitt's answer, here's my take on the problem:
<?php
function insertSoftBreak($string, $interval=20, $breakChr='­') {
$splitString = explode(' ', $string);
foreach($splitString as $key => $val) {
if(strlen($val)>$interval) {
$splitString[$key] = wordwrap($val, $interval, $breakChr, true);
}
}
return implode(' ', $splitString);
}
$string = 'Hello, My name is fwwfdfhhhfhhhfrhgrhffwfweronwefbwuecfbryhfbqpibcqpbfefpibcyhpihbasdcbiasdfayifvbpbfawfgawg, because that is my name.';
echo insertSoftBreak($string);
?>
Breaking the string up in space-seperated values, check the length of each individual 'word' (words include symbols like dot, comma, or question mark). For each word, check if the length is longer than $interval characters, and if so, insert a ­ (soft hyphen) every $interval'th character.
I've chosen soft hyphens because they seem to be relatively well-supported across browsers, and they usually don't show unless the word actually wraps at that position.
I'm not aware of any other usable (and well supported) HTML entities that could be used instead (‌ does not seem to work in FF 3.6, at least), so if crossbrowser support for ­ turns out lacking, a pure CSS or Javascript-based solution would be best.

How to remove a long word from a string

If a user types a really long string it doesn't move onto a 2nd line and will break a page on my site. How do I take that string and remove it completely if it's not a URL?
Why would you want to remove what the user wrote? Instead, wrap it to a new line - there is a function in PHP to do that, called wordwrap
Do you really want to remove the word, or do you just want to prevent it from making your page layout too wide? If the latter is more what you want, consider using CSS to manage the overflow.
For instance:
div {
overflow:hidden;
}
will hide any content that exceeds the div boundary.
Here's more info on CSS overflow:
http://www.w3schools.com/css/pr_pos_overflow.asp
// remove words over 30 chars long
$str = preg_replace('/\S{30,}/', '', $str);
edit: updated per Tim P's suggestion, \S matches any non-space char (the same as [^\s])
Also here is a better way incorporating ehdv's suggestion to use wordwrap:
//This will break up the long words with spaces so they don't stretch layouts.
$str = preg_replace('/(\S{30,})/e', "wordwrap('$1', 30, ' ', true)", $str);
What if it is a really long URL? At any rate why not just match the text to a valid URL, and only accept those? Check out some php-regex info on URLs and see how they work. The Regular Expressions Cookbook has a good chapter on URL matching, as well.
#Rob care in using REGEX. Performance lookout.

Categories