PHP loose typing in while loop comparison - php

Given the following code snippet:
$i= 11;
function get_num() {
global $i;
return (--$i >= 0) ? $i : false;
}
while($num = get_num()) {
echo "Number: $num\n";
}
Results in the following output:
Number: 10
Number: 9
Number: 8
Number: 7
Number: 6
Number: 5
Number: 4
Number: 3
Number: 2
Number: 1
However, I also want it to output Number: 0 - but the while loop evaluates 0 as being false, so the loop never gets to that point. How do I get the loop to terminate only on an explicit false?

while( ($num = get_num()) !== false ) {
extra = forces type check as well.

<?php
$i= 11;
function get_num() {
global $i;
return (--$i >= 0) ? $i : false;
}
while(($num = get_num())!==false) {
echo "Number: $num\n";
}
?>

You have to do a comparison that compares the types, and not only the values -- which means using the === or !== operators, instead of == or !=.
So, you could use something like :
while(($num = get_num()) !== false) {
echo "Number: $num\n";
}
With this, 0 will not be considered as the same thing as false.
As reference : Comparison Operators (quoting)
$a == $b : Equal : TRUE if
$a is equal to $b. $a === $b
: Identical : TRUE if $a is
equal to $b, and they are of the
same type.

I noticed that you are using global. Some devs scream about using global when not necessary. Also, you can leave out the parentheses if you write false!== before your $num declaration (no big deal, just a note).
Option 1
function get_num() {
static $i=11; // effectively only declare the value once
return (--$i >= 0) ? $i : false;
}
while(false!==$num=get_num()){
echo "Number: $num\n"; // $i is NOT available outside the scope of the function.
}
Option 2
function get_num($i) {
return (--$i >= 0) ? $i : false;
}
$num=11; // declare in global scope
while(false!==$num=get_num($num)){ // pass it to function as an argument
echo "Number: $num\n";
}

Related

&& operator in match

There are 4 variables, they all store numbers (numbers in the form of different representations)
All of these variables were placed in an unnamed array to test the type of the variables.
Inside the loop, there are 2 conditions that only work on certain variables ($a and $b).
The question is how to do the same in a match?
Namely, I'm interested in the implementation of several conditions (with the && operator) in match.
How to do it in a match:
if(is_integer($items) && $items == 1){}
elseif(is_numeric($items) && $items == 1.2){}
code with if:
$a = 1;
$b = 1.2;
$c = "1.5";
$d = 25;
function filter($massive) {
foreach($massive as $items){
if(is_integer($items) && $items == 1){ // works only with $a variable
echo "integer - {$items}";
}
elseif(is_numeric($items) && $items == 1.2){ // only $b
echo "numeric -{$items}";
}
else{
echo "other types - $items" ;
}echo"<br>";
}}
filter([$a, $b, $c, $d]);
My attempt with match:
$a = 1;
$b = 1.2;
$c = "1.5";
$d = 25;
function filter($massive) {
foreach($massive as $items){
echo match(true){
is_integer($items) => "integer -{$items}",
is_numeric($items) => "numeric - {$items}",
default => "other types - {$items}",
}."<br>";
}}
filter([$a, $b, $c, $d]);
Yes, you can use the logical AND (&&) operator in PHP match. If you get a syntax error about T_DOUBLE_ARROW, and you are sure you don't have a missing or extra opening or closing bracket or parenthesis, then it is possible that your PHP version is too old and you should either upgrade PHP to at least version 8 or use switch instead. match is a php8 feature.
<?php
$a = 1;
$b = 1.2;
$c = "1.5";
$d = 25;
function filter($massive) {
foreach($massive as $items){
echo match($items){
is_integer($items) && $items == 1 => "integer -{$items}",
is_numeric($items) && $items == 1.2 => "numeric - {$items}",
default => "other types - {$items}",
}."<br>";
}
}
filter([$a, $b, $c, $d]);
?>

PHP - Check if more than one condition is true in a given number of conditions

Is there an elegant way to check if multiple, but not all, conditions are true out of any given number of conditions?
For example, I have three variables: $a, $b, and $c.
I want to check that any two of these are true. So the following would pass:
$a = true;
$b = false;
$c = true;
But this wouldn't:
$a = false;
$b = false;
$c = true;
Also, I may want to check if 4 out of 7 conditions were true, for example.
I realise I can check each combination, but this would get more difficult as the number of conditions increased. Looping through the conditions and keeping a tally is the best option I can think of, but I thought there may be a different way to do this.
Thanks!
Edit: Thanks for all the great answers, they're much appreciated.
Just to throw a spanner in to the works, what if the variables weren't explicit booleans?
E.g.
($a == 2)
($b != "cheese")
($c !== false)
($d instanceof SomeClass)
A "true" boolean in PHP casts to a 1 as an integer, and "false" casts to 0. Hence:
echo $a + $b +$c;
...will output 2 if two out of the three boolean variables $a, $b or $c are true. (Adding the values will implicitly convert them to integers.)
This will also work with functions like array_sum(), so for example:
echo array_sum([true == false, 'cheese' == 'cheese', 5 == 5, 'moon' == 'green cheese']);
...will output 2.
You could put your variables in an array, and use array_filter() and count() to check the number of true values:
$a = true;
$b = false;
$c = true;
if (count(array_filter(array($a, $b, $c))) == 2) {
echo "Success";
};
I'd go for a method like the following:
if (evaluate(a, b, c))
{
do stuff;
}
boolean evaluate(boolean a, boolean b, boolean c)
{
return a ? (b || c) : (b && c);
}
What it says is:
If a is True, then one of b or c must be true too to comply with 2/3
True criterion.
Else, both b and c must be true!
If you want to expand and customise the conditions and the number of variables I'd go for for a solution like the following:
$a = true;
$b = true;
$c = true;
$d = false;
$e = false;
$f = true;
$condition = 4/7;
$bools = array($a, $b, $c, $d, $e, $f);
$eval = count(array_filter($bools)) / sizeof($bools);
print_r($eval / $condition >= 1 ? true : false);
Simply we evaluate the true's and we make sure that the % of True is equals or is better than what we want to achieve. Likewise you could manipulate the final evaluation expression to achieve what you want.
This should also work, and would allow you fairly easily to adjust to the numbers.
$a = array('soap','soap');
$b = array('cake','sponge');
$c = array(true,true);
$d = array(5,5);
$e = false;
$f = array(true,true);
$g = array(false,true);
$pass = 4;
$ar = array($a,$b,$c,$d,$e,$f,$g);
var_dump(trueornot($ar,$pass));
function trueornot($number,$pass = 2){
$store = array();
foreach($number as $test){
if(is_array($test)){
if($test[0] === $test[1]){
$store[] = 1;
}
}else{
if(!empty($test)){
$store[] = 1;
}
}
if(count($store) >= $pass){
return TRUE;
}
}
return false;
}
U can use while loop :
$condition_n = "x number"; // number of required true conditions
$conditions = "x number"; // number of conditions
$loop = "1";
$condition = "0";
while($loop <= $conditions)
{
// check if condition is true
// if condition is true : $condition = $condition + 1;
// $loop = $loop + 1;
}
if($condition >= $condition_n)
{
// conditions is True
}
else
{
// conditions is false
}
I think it is a little easy and short writing when you use operator "&" , "|" like this:
$a = true;
$b = true;
$c = false;
$isTrue = $a&$b | $b&$c | $c&$a;
print_r( $isTrue );
Let check by your self :D

How to test if $a is divisible by $b when $b is larger than $a

I'm trying to work out if one string, $a, is divisible by another, $b.
All of the examples I can find tell me to use modulus, e.g.:
if(($a %$b) == 0) : echo "Is dividible" ; endif;
However, because modulus returns the remainder of the calculation, this doesn't work if $b is larger than $a, because there's still no remainder.
How do I check divisibility where $b is sometimes (but not always) larger than $a?
why don't you do this as a function:
function isDivisible($smaller,$bigger){
//handle division by zero, and hmm.. let's cover negative numbers too
if($smaller<=0) return false;
if($smaller>$bigger) return false;
return !($bigger % $smaller);
}
The negation ! should be a working and elegant way to handle it.
How about:
echo ( ($a < $b) && (($a % $b) == 0) ) ? "Is dividible" : "Is not divisable" ;
if($a==$b)
{echo "divisible a and b are equal";
}
else if($a>$b){
if(($a %$b) == 0) : echo "Is dividible" ; endif;
}
else{
echo "\$b is either large or equal to \$a";
}
Try this it should work:
$a = 7;
$b = 14;
//echo ( ($a > $b) && ( ($a % $b) == 0) ) ? "is divisible":"no divisible";
echo ( ($a < $b) && (($b % $a) == 0) ) ? "Is dividible" : "Is not divisable" ;
You can use ternary operator as example given below
(($a%$b)==0)?echo "Is divisible": echo "not divisible";

! ( NULL || 0 || '' ) if condition in PHP at the same time

If I want to check the variable I need to do this:
if ( $i != '' || $i != 0 || $i != NULL ) {
// ...do some code
}
Could these 3 checks be somehow merged into 1 via some php function or a trick?
if (!empty($i)) {
// ... do some code
}
Please see http://php.net/manual/function.empty.php
All of them are actualy falsey. So you could do
if(!$i) {
}
http://php.net/manual/en/language.types.boolean.php
I should probably elaborate on why the OP has some bad assumptions. The list of things PHP will evaluate to false is long
When converting to boolean, the following values are considered FALSE:
the boolean FALSE itself
the integer 0 (zero)
the float 0.0 (zero)
the empty string, and the string "0"
an array with zero elements
the special type NULL (including unset variables)
SimpleXML objects created from empty tags
This is where equivalency comes into play. It's a comparison operator. The OP has this
if ( $i != '' || $i != 0 || $i != NULL )
All three are actually the same test. Take this code
$i = 0;
if($i == '') {
echo 'true';
}
if($i == 0) {
echo 'true';
}
if($i == NULL) {
echo 'true';
}
All three statements will echo out. So if you want to know if $i is actually NULL or false as opposed to 0 (and some functions will return both) you have to use a different operator. === is used to see if the two are equivalent and not simply equal.
$i = 0;
if($i == NULL) {
echo 'true'; //This will succeed
}
if($i === NULL) {
echo 'true'; //This will NOT succeed
}

Can I string along functions in an if statement and return a single variable?

I'm curious if it's possible to string along a couple possibilities for a function in an if statement, link them to a single variable and return the one that works, if any.
The following doesn't work, but it demonstrates the idea. I'd like the below to return 2 since the function myFn() only returns true when 2 is passed to it.
But instead the following returns true: 1.
if ($b = myFn(1) || $b = myFn(2) || $b = myFn(3)) {
echo 'true: ' . $b;
} else {
echo 'false: ' . $b;
}
function myFn($a) {
if ($a == 2) return $a;
return false;
}
Short of adding a series of elseifs, is there a way to string the functions in a series of ORs while only returning the successful one?
codepad: http://codepad.org/ldiCxY4j
Just wrap each assignment in parenthesis:
(($b = myFn(1)) || ($b = myFn(2)) || ($b = myFn(3)))
See: PHP operator precedence
When using logical operators, PHP coerces the result to boolean. Without the extra parens, it echoes '1' because echoing coerces true to '1'.
You may be better off using a loop:
/**
* Get the first $array value that passes the $test, or else null.
* #return mixed|null
*/
function find ($array, $test) {
foreach ($array as $index => $value) {
if (call_user_func($test, $value, $index, $array))
return $value;
}
}
For such concatenations of assignments PHP has the or operator, which is the same as || but with less precedence than =. This means that
if ($b = myFn(1) or $b = myFn(2) or $b = myFn(3))
is treated like:
if (($b = myFn(1)) or ($b = myFn(2)) or ($b = myFn(3)))
while
if ($b = myFn(1) || $b = myFn(2) || $b = myFn(3))
is treated like:
if ($b = (myFn(1) || $b = (myFn(2) || $b = myFn(3))))

Categories