Weird PHP "basic true / false declaration" results in two situations - php

I am confused with basic true / false declaration results in PHP code in two different situations. Lets assume that strlen($item["description"]) = 50. I want to add "..." if the description is longer than 20 characters.
Case 1:
$art = strlen($item["description"]) > 20 ? $item["description"] : substr($item["description"], 0, 20) . "...";
echo $art;
Case 2:
$cut = strlen($item["description"]) < 20 ? $item["description"] : substr($item["description"], 0, 20) . "...";
$art = $cut;
echo $art;
My question is: Why I have to change the "<" operator in Case 1 to ">", if I want to add "..." for bigger than 20 char desc.? In Case 2 everything works fine (the first statement is true and the second false).
Thanks for help!

This works like this
$var = condition ? true returns : false returns
So in your case1 you have the following code
$art = strlen($item["description"]) > 20 ? $item["description"] : substr($item["description"], 0, 20) . "...";
echo $art;
You are saying in this code that if it's bigger than 20 return your text else return the substring + "..."
Instead of changing the "<" or ">" change the returns like this
$art = strlen($item["description"]) > 20 ? substr($item["description"], 0, 20) . "..." : $item["description"] ;
echo $art;
In the second case
$cut = strlen($item["description"]) < 20 ? $item["description"] : substr($item["description"], 0, 20) . "...";
It's like
if(strlen($item["description"]) < 20)
{
return $item["description"];
}
else
{
return substr($item["description"], 0, 20) . "...";
}

Your code reads (1), if the string is greater than 20 characters, echo the string else echo the truncated string, with the elipsis.
Whereas the logic should read something like, if the string length is greater than 20 characters echo the truncated version else echo as is.
<?php
function truncate($str) {
return strlen($str) > 20
? substr($str, 0, 20) . "..."
: $str;
}
foreach(
[
'Who are you?',
'Sometimes it\'s harder to look than to leap.'
]
as
$text
)
echo truncate($text) , "\n";
Output:
Who are you?
Sometimes it's harde...
Your second case reads fine, if the string is less than 20 chars, assign the string as is, else truncate it with the elipsis.
The ternary operator is useful shorthand for an if, else statement.

Related

How to do $string = if(in range)?

Basically I'm trying to achieve this:
// generating a random number
$randomid = rand(261, 270);
//if range is between numbers, assign strings
$verticalaa = if ($randomid >= 261 && $randomid <= 265);
$verticalbb = if ($randomid >= 266 && $randomid <= 270);
//echo the range string name
echo 'random range is in' . $verticalaa . '' . $verticalbb . '';
In the end I want to echo the name of matching range.
If the number is, let's say, 262, it would echo verticalaa.
I hope it's possible to understand what I'm after.
My head is like a balloon now after hours of coding.
Need help.
Probably an easier way to this would be ternary and assign 1 variable.
$randomid = rand(261, 270);
$var = in_array($randomid, range(261, 265)) ? 'between 261 and 265' : 'between 266 and 270';
echo $var;
For readability purpose for long lists you can use switch operator in this way:
switch (true)
{
case $a > 100: $result = 'aaa'; break;
case $a > 90: $result = 'bbb'; break;
case $a > 80: $result = 'ccc'; break;
// ...
case $a > 0: $result = 'zzz'; break;
}
At the same time, your question looks like a classic XY problem and what you ask is not what you need.

PHP: Declaring if a value is odd or even from a random integer [duplicate]

This question already has answers here:
Test if number is odd or even
(20 answers)
Closed 5 years ago.
I don't know where I am going wrong with my code and I am asking for some guidance as I am new to PHP.
I am trying to do an If else statement that will display if the random integer is odd or even. When I run the code it keeps on showing 'Number is odd' or nothing and I am not sure why. Any guidance will be much appreciated.
$RandomValue = rand(0, 10);
$OddValues = (1 || 3 || 5 || 7 || 9);
$EvenValues = (0 || 2 || 4 || 6 || 8 || 10);
if($RandomValue == $OddValues) {
echo $RandomValue, ' Number is odd';
} else {
if($RandomValue == $EvenValues)
echo $RandomValue, ' Number is even';
}
There is a much easier way to do this. Use the modulo operator in php which is written as %. The modulo operator essentially returns 0 if there's no remainder and the remainder if there is. In this case, you're looking to just divide by 2 and see if anything remains, that's what modulo is doing here. So the only thing it's going to return is either 0 or 1.
$x = 3;
if($x % 2 == 0) { //number is even}
else { //number is odd }
Check it like
if ($RandomValue % 2 === 0) {
echo "$RandomValue is even";
} else {
echo "$RandomValue is odd";
}
For reference, see:
http://php.net/manual/en/language.operators.arithmetic.php
https://en.wikipedia.org/wiki/Modulo_operation
You can also check using the bitwise &
$is_odd = $x & 1;
Such as this
$nums = [1,2,3,4,5,6,7,8,9,10];
foreach( $nums as $x ){
$is_odd = $x & 1;
echo $is_odd ? 'ODD' : 'EVEN';
echo "\n";
}
Output
ODD
EVEN
ODD
EVEN
ODD
EVEN
ODD
EVEN
ODD
EVEN
You can test it here
http://sandbox.onlinephpfunctions.com/code/d47ab3970f24038afb28876b212a6f020eb0a0aa
And for a complete answer to your question
$RandomValue = rand(0, 10);
if($RandomValue & 1) {
echo $RandomValue. ' Number is odd';
} else {
echo $RandomValue. ' Number is even';
}
PS. you also have a comma and not a . here
echo $RandomValue, ' Number is odd';
http://sandbox.onlinephpfunctions.com/code/e2573a5dfe0e5aec6c0bfac3ce62c6788b070641
And indeed we can condense this a bit more into only 2 lines
$RandomValue = rand(0, 10);
echo $RandomValue. ' Number is '.($RandomValue & 1 ? 'even' : 'odd');
Oh and if you are not sure what the & "single and" is ( or bitwise in general ):
http://php.net/manual/en/language.operators.bitwise.php
Use Modulo.
if($RandomValue % 2 === 0){ echo $RandomValue, ' Number is even'; }
you can use ternary operator and do the test in one line :
function evenOrOdd($number)
{
return 0 === $number % 2 ? 'even' : 'odd';
}

Why does this for-loop comparison fail after auto-incrementing on letters

I just gave this answer : https://stackoverflow.com/a/25688064/2627459 in order to loop over letters combination, with the following code :
for ($letter = 'a'; ; ++$letter) {
echo $letter . '<br>';
if ($letter == 'zz') break;
}
Which is just working fine.
I then tried to move the break into the for loop comparison, feeling that it would be better :
for ($letter = 'a'; $letter < 'zz'; ++$letter) {
echo $letter . '<br>';
}
But of course, the last value (zz) wasn't showing, so I tried :
for ($letter = 'a'; $letter < 'aaa'; ++$letter) {
echo $letter . '<br>';
}
And I don't know why, but it's giving me the following output :
a
So I tried several entries, and the (weird) results are :
Entry : $letter < 'yz' -
Output : Up to y only
Entry : $letter < 'zzz' -
Output : Up to zzy
I don't get why it works when the chain starts with z, but it fails in any other case (letter).
Morover, in the case of $letter < 'aaa', it displays a, but not the next one. At worst, I would have expected it to fail with a < 'aaa' and so display nothing. But no.
So, where does this behavior come from, am I missing something on how PHP compare these values ?
(I'm not looking for a workaround, but for an explanation. By the way, if any explanation comes with a working code, it's perfect !)
Comparison is alphabetic:
$letter < 'yz'
When you get to y, you increment again and get z..... alphabetically, z is greater than yz
If you use
$letter != 'yz'
for your comparison instead, it will give you up to yy
So
for ($letter = 'a'; $letter !== 'aaa'; ++$letter) {
echo $letter . '<br>';
}
will give from a, through z, aa, ab.... az, ba.... through to zz.
See also this answer and related comments
EDIT
Personally I like incrementing the endpoint, so
$start = 'A';
$end = 'XFD';
$end++;
for ($char = $start; $char !== $end; ++$char) {
echo $char, PHP_EOL;
}

PHP: How to check if a number has more than two decimals

I'm trying to pick out numbers with more than two decimals (more than two digits after the decimal separator). I cant't figure out why this doesn't work:
if ($num * 100 != floor($num * 100)) {
echo "The number you entered has more than two decimals";
}
Why is the number 32.45 picked out, while 32.44 isn't?
You could use a regex:
$number = 1.12; //Don't match
$number = 1.123; //Match
$number = 1.1234; //Match
$number = 1.123; //Match
if (preg_match('/\.\d{3,}/', $number)) {
# Successful match
} else {
# Match attempt failed
}
You can use a regex to figure out if it has more than 2 decimals:
<?php
function doesNumberHaveMoreThan2Decimals($number) {
return (preg_match('/\.[0-9]{2,}[1-9][0-9]*$/', (string)$number) > 0);
}
$numbers = array(123.456, 123.450, '123.450', 123.45000001, 123, 123.4);
foreach ($numbers as $number) {
echo $number . ': ' . (doesNumberHaveMoreThan2Decimals($number) ? 'Y' : 'N') . PHP_EOL;
}
?>
Output:
123.456: Y
123.45: N
123.450: N
123.45000001: Y
123: N
123.4: N
DEMO
Regex autopsy (/\.[0-9]{2,}[1-9][0-9]*$/):
\. - a literal . character
[0-9]{2,} - Digits from 0 to 9 matched 2 or more times
[1-9] - A digit between 1 and 9 matched a single time (to make sure we ignore trailing zeroes)
[0-9]* - A digit between 0 and 9 matched 0 to infinity times (to make sure that we allow 123.4510 even though it ends with 0).
$ - The string MUST end here - nothing else can be between our last match and the end of the string
You could use the following function (works with negative numbers, too):
function decimalCheck($num) {
$decimals = ( (int) $num != $num ) ? (strlen($num) - strpos($num, '.')) - 1 : 0;
return $decimals >= 2;
}
Test cases:
$numbers = array(
32.45,
32.44,
123.21,
21.5454,
1.545400,
2.201054,
0.05445,
32,
12.0545400,
12.64564,
-454.44,
-0.5454
);
foreach ($numbers as $number) {
echo $number. "\t : \t";
echo (decimalCheck($number)) ? 'true' : 'false';
echo "<br/>";
}
Output:
32.45 : true
32.44 : true
123.21 : true
21.5454 : true
1.5454 : true
2.201054 : true
0.05445 : true
32 : false
12.05454 : true
12.64564 : true
-454.44 : true
-0.5454 : true
Demo.
I know, its an old question, but why not just do:
function onlyDecimals($number, $maxDecimalPlaces = 2) {
return $amount == number_format($amount, $maxDecimalPlaces, ".", "");
}
See example and tests: http://sandbox.onlinephpfunctions.com/code/e68143a9ed0b6dfcad9ab294c44fa7e802c39dd0

Add space after every 4th character

I want to add a space to some output after every 4th character until the end of the string.
I tried:
$str = $rows['value'];
<? echo substr($str, 0, 4) . ' ' . substr($str, 4); ?>
Which just got me the space after the first 4 characters.
How can I make it show after every 4th ?
You can use chunk_split [docs]:
$str = chunk_split($rows['value'], 4, ' ');
DEMO
If the length of the string is a multiple of four but you don't want a trailing space, you can pass the result to trim.
Wordwrap does exactly what you want:
echo wordwrap('12345678' , 4 , ' ' , true )
will output:
1234 5678
If you want, say, a hyphen after every second digit instead, swap the "4" for a "2", and the space for a hyphen:
echo wordwrap('1234567890' , 2 , '-' , true )
will output:
12-34-56-78-90
Reference - wordwrap
Have you already seen this function called wordwrap?
http://us2.php.net/manual/en/function.wordwrap.php
Here is a solution. Works right out of the box like this.
<?php
$text = "Thiswordissoverylong.";
$newtext = wordwrap($text, 4, "\n", true);
echo "$newtext\n";
?>
Here is an example of string with length is not a multiple of 4 (or 5 in my case).
function space($str, $step, $reverse = false) {
if ($reverse)
return strrev(chunk_split(strrev($str), $step, ' '));
return chunk_split($str, $step, ' ');
}
Use :
echo space("0000000152748541695882", 5);
result: 00000 00152 74854 16958 82
Reverse mode use ("BVR code" for swiss billing) :
echo space("1400360152748541695882", 5, true);
result: 14 00360 15274 85416 95882
EDIT 2021-02-09
Also useful for EAN13 barcode formatting :
space("7640187670868", 6, true);
result : 7 640187 670868
short syntax version :
function space($s=false,$t=0,$r=false){return(!$s)?false:(($r)?trim(strrev(chunk_split(strrev($s),$t,' '))):trim(chunk_split($s,$t,' ')));}
Hope it could help some of you.
On way would be to split into 4-character chunks and then join them together again with a space between each part.
As this would technically miss to insert one at the very end if the last chunk would have exactly 4 characters, we would need to add that one manually (Demo):
$chunk_length = 4;
$chunks = str_split($str, $chunk_length);
$last = end($chunks);
if (strlen($last) === $chunk_length) {
$chunks[] = '';
}
$str_with_spaces = implode(' ', $chunks);
one-liner:
$yourstring = "1234567890";
echo implode(" ", str_split($yourstring, 4))." ";
This should give you as output:
1234 5678 90
That's all :D
The function wordwrap() basically does the same, however this should work as well.
$newstr = '';
$len = strlen($str);
for($i = 0; $i < $len; $i++) {
$newstr.= $str[$i];
if (($i+1) % 4 == 0) {
$newstr.= ' ';
}
}
PHP3 Compatible:
Try this:
$strLen = strlen( $str );
for($i = 0; $i < $strLen; $i += 4){
echo substr($str, $i, 4) . ' ';
}
unset( $strLen );
StringBuilder str = new StringBuilder("ABCDEFGHIJKLMNOP");
int idx = str.length() - 4;
while (idx > 0){
str.insert(idx, " ");
idx = idx - 4;
}
return str.toString();
Explanation, this code will add space from right to left:
str = "ABCDEFGH" int idx = total length - 4; //8-4=4
while (4>0){
str.insert(idx, " "); //this will insert space at 4th position
idx = idx - 4; // then decrement 4-4=0 and run loop again
}
The final output will be:
ABCD EFGH

Categories