Alternative to in_array or multiple OR in if-statement - php

So, as the title says... any alternative to:
$valid_times = array('ever', 'today', 'week', 'month');
if (($this->_time == 'ever') OR ($this->_time == 'day'))
OR
if (in_array($this->_time, $valid_times))
??
Note: I know the mentioned above works, but I'm just looking for new things to learn and experiment with
UPDATE
Thanks for the info, but I didn't mentioned switch() as an alternative because it's not the case for my code. It has to be an if-statement, and I was wondering if exists something like:
if($this->_time == (('ever') OR ('day') OR ('month')))
What do you think? That would be a shorter way of the first if mentioned above

What about ?
$a1 = array("one","two","three");
$found = "two";
$notFound = "four";
if (count(array_diff($a1,array($found))) != count($a1))
/* Found */
Either you can use
$found = array("one","three");
if (count(array_diff($a1,$found)) != count($a1));
/* Either one OR three */
http://codepad.org/FvXueJkE

The only alternative I can think to accomplish this would be using regex.
$valid_times = array('ever','day','week','hour');
if(preg_match('/' . implode('|', $valid_times) . '/i', $this->_time)){
// match found
} else {
// match not found
}

[EDIT] Removed original answer since you've now specified you don't want to use switch.
In your updated question, you asked if something like this is possible:
if($this->_time == (('ever') OR ('day') OR ('month')))
The direct answer is 'no, not in PHP'. The closest you'll get is in_array(), with the array values in place in the same line of code:
if(in_array($this->_time, array('ever','day','month'))
PHP 5.4 has an update allows for shorter array syntax, which means you can drop the word array, which makes it slightly more readable:
if(in_array($this->_time, ['ever','day','month'])
But it is still an in_array() call. You can't get around that.

Sometime like this for in_array?
$arr = array(1, 2, 'test');
$myVar = 2;
function my_in_array($val, $arr){
foreach($arr as $arrVal){
if($arrVal == $val){
return true;
}
}
return false;
}
if(my_in_array($myVar, $arr)){
echo 'Found!';
}

Convoluted, but it is an alternative
$input = 'day';
$validValues = array('ever','day');
$result = array_reduce($validValues,
function($retVal,$testValue) use($input) {
return $retVal || ($testValue == $input);
},
FALSE
);
var_dump($result);

You could also use the switch statement.
switch ($this->_time) {
case 'ever':
case 'day':
//code
break;
default:
//something else
}

For the sake of science, it turns out you can use yield in a ternary operator, so you could put some complex evaluations in a anonymous generator, and have it yield on the first one that evaluates to true, without needing to evaluate them all:
$time = 'today';
if( (function()use($time){
$time == 'ever' ? yield true:null;
$time == 'today' ? yield true:null;
$time == 't'.'o'.'d'.'a'.'y' ? yield true:null;
})()->current() ){
echo 'valid';
}
In this case it will echo 'valid' without ever evaluating the concatenation.

Related

Boolean has wrong value after operation [duplicate]

I remember reading a while back in regards to logical operators that in the case of OR, using || was better than or (or vice versa).
I just had to use this in my project when it came back to me, but I can't remember which operator was recommended or if it was even true.
Which is better and why?
There is no "better" but the more common one is ||. They have different precedence and || would work like one would expect normally.
See also: Logical operators (the following example is taken from there):
// The result of the expression (false || true) is assigned to $e
// Acts like: ($e = (false || true))
$e = false || true;
// The constant false is assigned to $f and then true is ignored
// Acts like: (($f = false) or true)
$f = false or true;
They are used for different purposes and in fact have different operator precedences. The && and || operators are intended for Boolean conditions, whereas and and or are intended for control flow.
For example, the following is a Boolean condition:
if ($foo == $bar && $baz != $quxx) {
This differs from control flow:
doSomething() or die();
The difference between respectively || and OR and && and AND is operator precedence :
$bool = FALSE || TRUE;
interpreted as ($bool = (FALSE || TRUE))
value of $bool is TRUE
$bool = FALSE OR TRUE;
interpreted as (($bool = FALSE) OR TRUE)
value of $bool is FALSE
$bool = TRUE && FALSE;
interpreted as ($bool = (TRUE && FALSE))
value of $bool is FALSE
$bool = TRUE AND FALSE;
interpreted as (($bool = TRUE) AND FALSE)
value of $bool is TRUE
Source: http://wallstreetdeveloper.com/php-logical-operators/
Here is sample code for working with logical operators:
<html>
<head>
<title>Logical</title>
</head>
<body>
<?php
$a = 10;
$b = 20;
if ($a>$b)
{
echo " A is Greater";
}
elseif ($a<$b)
{
echo " A is lesser";
}
else
{
echo "A and B are equal";
}
?>
<?php
$c = 30;
$d = 40;
//if (($a<$c) AND ($b<$d))
if (($a<$c) && ($b<$d))
{
echo "A and B are larger";
}
if (isset($d))
$d = 100;
echo $d;
unset($d);
?>
<?php
$var1 = 2;
switch($var1)
{
case 1: echo "var1 is 1";
break;
case 2: echo "var1 is 2";
break;
case 3: echo "var1 is 3";
break;
default: echo "var1 is unknown";
}
?>
</body>
</html>
I know it's an old topic but still. I've just met the problem in the code I am debugging at work and maybe somebody may have similar issue...
Let's say the code looks like this:
$positions = $this->positions() || [];
You would expect (as you are used to from e.g. javascript) that when $this->positions() returns false or null, $positions is empty array. But it isn't. The value is TRUE or FALSE depends on what $this->positions() returns.
If you need to get value of $this->positions() or empty array, you have to use:
$positions = $this->positions() or [];
EDIT:
The above example doesn't work as intended but the truth is that || and or is not the same... Try this:
<?php
function returnEmpty()
{
//return "string";
//return [1];
return null;
}
$first = returnEmpty() || [];
$second = returnEmpty() or [];
$third = returnEmpty() ?: [];
var_dump($first);
var_dump($second);
var_dump($third);
echo "\n";
This is the result:
bool(false)
NULL
array(0) {
}
So, actually the third option ?: is the correct solution when you want to set returned value or empty array.
$positions = $this->positions() ?: [];
Tested with PHP 7.2.1
I don't think one is inherently better than another one, but I would suggest sticking with || because it is the default in most languages.
EDIT: As others have pointed out there is indeed a difference between the two.
There is nothing bad or better, It just depends on the precedence of operators. Since || has higher precedence than or, so || is mostly used.
Some languages use short-circuit, and others use full Boolean evaluation (if you know, this is similar to the directive $B in Pascal).
Explanations:
function A(){
...Do something..
return true;
}
function B(){
...Do something..
return true;
}
if ( A() OR B() ) { .....
In this example the function B() will never be executed. Since the function A() returns TRUE, the result of the OR statement is known from the first part without it being necessary to evaluate the second part of the expression.
However with ( A() || B() ), the second part is always evaluated regardless of the value of the first.
For optimized programming, you should always use OR which is faster (except for the case when the first part returns false and second part actually needs to be evaluated).

How can I check if a string contains characters stored in an array but return false if it contains any characters not in the array

Basically I'm checking days of the week from an array to a string based on an initialization of the day for instance:
<?php
$check_days = array("M", "T");
$days1 = "MTW";
$days2 = "M";
[insert code to compare $check_days to $days1 and $days2 so that $days1 returns FALSE while $days2 returns TRUE]
?>
Try using a regex character class and implode:
if (preg_match('/^['.implode($check_days).']+$/', $days1)) {
// do some stuff
}
EDIT: Let me help explain what's going on here:
implode($check_days)
This combines all the elements of an array into a single string. In your case, this is "MT".
preg_match('/^[MT]+$/', $days1);
This is a regular expression that checks that after the 'beginning' (^), $days1 contains either an "M" or a "T" ([MT]), repeated one or more times (+), then the string ends ($). It returns true if this is the case.
Hope that helps.
Sorry, I read your question wrong, and so my answer is wrong too. I'd go with wavemode's solution.
Original answer
If I understand your requirements correctly, you want to make sure all the days in check_days must exist in the variable to be tested. If I'm correct, this function will work:
function checkDays($haystack, $validator) {
$ok = true;
foreach ($validator as $day) {
$ok = (strpos($haystack, $day) !== false) && $ok;
}
return $ok;
}
See it in action in this phiddle: http://phiddle.net/6
Try this:
function checkDays($testFor, $inString){
$a = str_split($inString); $d = array();
foreach($a as $v){
if(!in_array($testFor, $v) || in_array($d, $v)){
return false;
}
$d[] = $v;
}
return true;
}
$check_days = array('M', 'T');
echo checkDays($check_days, 'MTW');
echo checkDays($checkdays, 'M');

PHP combined operator for &&?

I have code like this:
$finalResult = true;
$finalResult = $finalResult && function_01();
// some code here
$finalResult = $finalResult && function_02();
// some many lines of code here
$finalResult = $finalResult && function_XX();
And I'm looking for a way how to shorten the code (just for a human-readibility reasons) to something like:
$finalResult = true;
$finalResult &&= function_01();
// some code here
$finalResult &&= function_02();
// some many lines of code here
$finalResult &&= function_XX();
But of course this doesn't work and operator &= is not for boolean values, but for binary.
How should I do this ?
Thanks.
$names = array('function01','function02'...);
$result = true;
foreach($names as $caller)
{
$result = $result && $caller();
}
otherwise instead of $caller() you could look for call_user_func ( http://us3.php.net/call_user_func )
it's not really fantastic, but it's shorter :/ not a big deal
edit:
uhm... i guess that after your edit this solution is not more functional... should i delete it ?
I would also reconsider the logic of your code by adding a class that makes these checks: if all the checking logic is in a class whose purpose is just that you could surely benefit of readability
Stormsson's but improved - finish as soon as you know the result:
$names = array( 'function01','function02'... );
$result = true;
foreach( $names as $caller )
{
if ( $result == false ) break; // short circuit
$ret = $caller()
if ( $ret == false )
{
$result = false;
break; // short circuit
}
$result = $result && $ret;
}
OK, after all it seems I will not get it any simpler than original.
For those of you who don't understand why I want to have it in some "short" form - only reason was to have it shorter and nicer. Just the same reason why there is possibility to write $a += 3 just for beauty.
Anyway, thanks to everybody :)

Something wrong with my second else statement?

<?php
$check = array ("85.49.","85.62.");
foreach($check as $var) {
if (ereg($var, $_SERVER['REMOTE_ADDR'])) {
$intruder = 0;
}
else {
$intruder = 1;
}
if ($intruder = 0);
echo 'bugger off';
}
else{
echo 'welcome';
}
?>
What could be wrong with my second else? Dreamweaver red flags it and my server says error. All I want to do is get it to behave one way or another if $intruder is 1 or 0.
if ($intruder = 0);
First, you have an extra semicolon, so the body of the if statement is empty.
Secondly, = is assignment, you need comparison: ==.
The structure is not clear, but probably the next problem is your loop, which will overwrite $intruder in each iteration, so at the end it will contain the result of the last comparison.
The problem you ask about is on this line:
if ($intruder = 0);
You should be using == to compare the values, not = which is for assignment. And you should have a curly brace { after that instead of a semicolon.
Also, all of the ereg* functions are deprecated and should not be used. They will eventually be removed from the language entirely. To check if a word contains another word, just use strpos.
Your logic is also wrong for what you appear to be doing. You need to not overwrite the values of $intruder in each iteration of the loop. Set it to 0 before the loop, set it to 1 if there's a match in the loop, then after the loop is complete you'll know if there was a match during any of the comparisons and can print the appropriate message.
$found = 0;
foreach ($check as $var) {
if (strpos($_SERVER['REMOTE_ADDR'], $var) === 0) {
$found= 1;
}
}
if ($found == 1) {
echo "You are in my list.";
} else {
echo "You are not in my list.";
}
?>
Change this:
if ($intruder = 0);
To this:
if ($intruder == 0) {
First error:
if ($intruder = 0);
fix it in this way:
if ($intruder == 0)
echo 'bugger off';
else
echo 'welcome';
Second error:
The use of ereg is deprecated. Replace it with preg_match(); http://www.php.net/manual/en/function.preg-match.php
Friend, please do not be offended, but I'd rather have asked "is there anything right in this code?"
<?php
$check = array ("85.49.","85.62.");
foreach($check as $var) {
// Here you use the deprecated ereg instead of preg_match or, better, strpos
// However, the regular expressions would be wrong - what if 192.85.49.3 comes by?
if (ereg($var, $_SERVER['REMOTE_ADDR'])) {
$intruder = 0;
}
else {
$intruder = 1;
}
// Here you do not close the foreach, so that the following code gets executed
// repeatedly
// Here you place a ; after the if, so the if body is empty and bugger off gets
// triggered always.
// Which changes little, since $intruder = 0 is an assignment (use == instead)
// (see note)
if ($intruder = 0);
echo 'bugger off';
}
// Anyway, logically "$intruder == 0" means "NOT an intruder", so you are actually
// telling friends to bugger off and welcome intruders :-)
else{
echo 'welcome';
}
?>
Note: it is maybe voodoo programming (I found it on Maguire's 'Writing Solid Code'), but I think you might get into the habit of checking values the other way:
if (0 == $intruder)
This way if you ever drop a = again, it will not create a new statement doing something you wouldn't want, but it will become a syntax error that makes itself immediately visible.
Anyway, the code for what you want should be:
<?php
$check = array ("85.49.","85.62.");
$matches = false;
foreach($check as $var)
{
if (0 === strpos($_SERVER['REMOTE_ADDR'], $var))
{
$matches = true;
// There is one match, no sense in checking further
break;
}
}
if ($matches)
{
// He is in our little list - tell him something
print "You match.";
}
?>
Simple yaar.Just edit:
if ($intruder == 0);
echo 'bugger off';
}
else{
echo 'welcome';
}

Logical Operators, || or OR?

I remember reading a while back in regards to logical operators that in the case of OR, using || was better than or (or vice versa).
I just had to use this in my project when it came back to me, but I can't remember which operator was recommended or if it was even true.
Which is better and why?
There is no "better" but the more common one is ||. They have different precedence and || would work like one would expect normally.
See also: Logical operators (the following example is taken from there):
// The result of the expression (false || true) is assigned to $e
// Acts like: ($e = (false || true))
$e = false || true;
// The constant false is assigned to $f and then true is ignored
// Acts like: (($f = false) or true)
$f = false or true;
They are used for different purposes and in fact have different operator precedences. The && and || operators are intended for Boolean conditions, whereas and and or are intended for control flow.
For example, the following is a Boolean condition:
if ($foo == $bar && $baz != $quxx) {
This differs from control flow:
doSomething() or die();
The difference between respectively || and OR and && and AND is operator precedence :
$bool = FALSE || TRUE;
interpreted as ($bool = (FALSE || TRUE))
value of $bool is TRUE
$bool = FALSE OR TRUE;
interpreted as (($bool = FALSE) OR TRUE)
value of $bool is FALSE
$bool = TRUE && FALSE;
interpreted as ($bool = (TRUE && FALSE))
value of $bool is FALSE
$bool = TRUE AND FALSE;
interpreted as (($bool = TRUE) AND FALSE)
value of $bool is TRUE
Source: http://wallstreetdeveloper.com/php-logical-operators/
Here is sample code for working with logical operators:
<html>
<head>
<title>Logical</title>
</head>
<body>
<?php
$a = 10;
$b = 20;
if ($a>$b)
{
echo " A is Greater";
}
elseif ($a<$b)
{
echo " A is lesser";
}
else
{
echo "A and B are equal";
}
?>
<?php
$c = 30;
$d = 40;
//if (($a<$c) AND ($b<$d))
if (($a<$c) && ($b<$d))
{
echo "A and B are larger";
}
if (isset($d))
$d = 100;
echo $d;
unset($d);
?>
<?php
$var1 = 2;
switch($var1)
{
case 1: echo "var1 is 1";
break;
case 2: echo "var1 is 2";
break;
case 3: echo "var1 is 3";
break;
default: echo "var1 is unknown";
}
?>
</body>
</html>
I know it's an old topic but still. I've just met the problem in the code I am debugging at work and maybe somebody may have similar issue...
Let's say the code looks like this:
$positions = $this->positions() || [];
You would expect (as you are used to from e.g. javascript) that when $this->positions() returns false or null, $positions is empty array. But it isn't. The value is TRUE or FALSE depends on what $this->positions() returns.
If you need to get value of $this->positions() or empty array, you have to use:
$positions = $this->positions() or [];
EDIT:
The above example doesn't work as intended but the truth is that || and or is not the same... Try this:
<?php
function returnEmpty()
{
//return "string";
//return [1];
return null;
}
$first = returnEmpty() || [];
$second = returnEmpty() or [];
$third = returnEmpty() ?: [];
var_dump($first);
var_dump($second);
var_dump($third);
echo "\n";
This is the result:
bool(false)
NULL
array(0) {
}
So, actually the third option ?: is the correct solution when you want to set returned value or empty array.
$positions = $this->positions() ?: [];
Tested with PHP 7.2.1
I don't think one is inherently better than another one, but I would suggest sticking with || because it is the default in most languages.
EDIT: As others have pointed out there is indeed a difference between the two.
There is nothing bad or better, It just depends on the precedence of operators. Since || has higher precedence than or, so || is mostly used.
Some languages use short-circuit, and others use full Boolean evaluation (if you know, this is similar to the directive $B in Pascal).
Explanations:
function A(){
...Do something..
return true;
}
function B(){
...Do something..
return true;
}
if ( A() OR B() ) { .....
In this example the function B() will never be executed. Since the function A() returns TRUE, the result of the OR statement is known from the first part without it being necessary to evaluate the second part of the expression.
However with ( A() || B() ), the second part is always evaluated regardless of the value of the first.
For optimized programming, you should always use OR which is faster (except for the case when the first part returns false and second part actually needs to be evaluated).

Categories