Correct way with in_array - php

I have a problem with in_array giving me a notice: undefined index.
if (
($value['device'] == $this->device or $value['device'] == 'all')
and
(!is_array($value['excludeLang']) or !in_array($this->lang, $value['excludeLang']))
and
($value['site'] == $this->site or $value['site'] == 'all')
) {
// do something
}
In this case $value['excludeLang'] is not an array. Is there a way of suppressing the error when I check if $this->lang is in the array

(!isset($value['excludeLang']) or !is_array($value['excludeLang']) or !in_array($this->lang, $value['excludeLang']))

I would use isset(), specifically with your example I'd write it as follows:
if (
($value['device'] == $this->device or $value['device'] == 'all')
and
(!isset($value['excludeLang']) or !is_array($value['excludeLang']) or !in_array($this->lang, $value['excludeLang']))
and
($value['site'] == $this->site or $value['site'] == 'all')
) {
// do something
}
The reason this works, and I think it's important to bear this in mind, is because of the way || (or) conditions are evaluated in PHP.
Take the condition
if ($condition1 || $condition2)
Only one thing in an or statement needs to be evaluated as being true. PHP is evaluated left to right, and so in this case if $condition1 is evaluated as true, PHP won't bother to check $condition2.
In your specific case, if !isset($value['excludeLang']) is evaluated as being true, it will never get as far as trying to run in_array, it will skip all the other conditions, return true and continue.

Related

PHP - if single value equals multiple options

So I understand this - and comparing/checking values. However, I was messing about and noticed the outcome for all my tests were the same - some of which I was taught (a) didn't work or (b) was incorrect.
Note, I'm running PHP7. Okay, to my point. I was able to achieve the same outcome checking if a single value equals one of multiple options...
These work...why? Def not the way I learned.
if ($status == 'in-progress' || 'in-review')
// and even
if ($status == ('in-progress' || 'in-review')) // kind of similar to ASP.NET Razor
I normally would repeat the check, like so: if($stat == 'a' || $stat == 'b') or even in_array() which is essentially the same thing.
Is the first examples, correct? If not, why is it working? Or is this something frowned upon and not practiced - or maybe even something new?
First off to make it clear == has a higher precedence than ||. This means your two if statements look like this:
if (($status == 'in-progress') || 'in-review')
if ($status == ('in-progress' || 'in-review'))
Now for your first if statement regardless what value $status has and what the outcome of ($status == 'in-progress') is, since you have an OR in it and after it 'in-review' your if statement will always be true, since a non empty string is a truthy value.
For your second statement, this part ('in-progress' || 'in-review') comes literally down to TRUE || TRUE, which evaluates to TRUE. Now $status just needs to hold a truthy value and the if statement will be true.
No, that code will never work. || has a lower precedence than ==, so you're comparing $status against the first value, then boolean || "or" the other value
if (($status == 'foo') || ('bar'))
You have to compare the values individually:
if (($status == 'foo') || ($status == 'bar'))
And this gets tedious for many values. A quick hack is to use an array:
if (in_array($status, array('foo', 'bar', 'baz', 'qux', 'etc...')))

Function executing order in an if statement php

I want to make a function for a "secure" php page that will check the token(the one passed by post and the one from the session). But I don't want to write two if statements like this:
function CheckToken(){
if(isset($_POST['token']) && isset($_SESSION['token']))
if($_POST['token']==$_SESSION['token']) return true;
return false;
}
Can I do something like this(?):
function CheckToken(){
if(isset($_POST['token']) && isset($_SESSION['token']) && $_POST['token']==$_SESSION['token']) return true;
return false;
}
Here's all about the order in which those functions are executed (when using the and operator).So if you're using the AND operand then if the first conditions is false don't evaluate the second. I remember that vb.net had a solution to this problem(evaluating only the first function-if it is false don't evaluate the second one). So, is it safe to put everything on a single line(like I did in the second example)?
PHP does the same thing as the usual if statement evaluation in other major languages, that is, check from left to right.
So if you have
if (cond1 && cond2 && cond3)
Scenario 1:
If cond1 is true, it will then execute cond2, and then cond3.
Sample: https://3v4l.org/Ap9SQ
Scenario 2:
If let's say cond2 is false, then cond3 will be ignored.
Sample: https://3v4l.org/u9P4O
Same goes to OR
if (cond1 || cond2 || cond3)
If cond1 is true, cond2 and cond3 will be skipped.
Sample: https://3v4l.org/ZAZcD
So since your function is just returning true or false, you can even simplify it to something like this:
function CheckToken() {
return isset($_POST['token']) &&
isset($_SESSION['token']) &&
$_POST['token'] == $_SESSION['token'];
}
Split lines for readability. Also checkout isset manual as you can pass in multiple variables for empty checking.
Yes, there really is no difference to changing the order like that. It is perfectly safe, because all it's doing is changing the look of the script while the execution is the EXACT same.
It would be best to do the second option.

What does while ($variable) mean in PHP?

I am new to PHP and am currently constructing a do/while loop from a tutorial. I would understand if the whole condition was ($variable == true) or ($variable == false), however in the tutorial the while condition is simply while($variable). Could anyone explain this to me?
Here is the tutorial code.
<?php
$loopCond = false;
do {
echo "<p>The loop ran even though the loop condition is false.</p>";
} while ($loopCond);
echo "<p>Now the loop is done running.</p>";
?>
All such conditional statements, including while and if, are evaluating the given expression against true. If the expression results in true, the statement executes the action. If it results in false, it won't.
$var == true is an expression which compares $var to true. The result of this expression is either true or false. The important point to understand here is expressions. Expressions are things which return values. Try var_dump($var == true) or var_dump(4 > 6). It shows you that the expressions return a boolean value. Here:
if ($var == true)
first $var is compared to true, which yields either the value true or false, which is then evaluated by if whether it's true or false, which then prompts if to execute the following statement or not.
In other words: it's redundant.
if ($var)
This simply causes if to evaluate whether $var is true or false and then execute the following statement. The == true is essentially already "built in".
The following statements are all essentially equivalent:
if ($var)
if ($var == true)
if (($var == true) == true)
if ((($var == true)) == true) == true)
...
A boolean value true or false should not be used with a redundant $c == true as the result is the same as $c: true or false
$driving = true;
while ($driving) {
while ($driving == true) { // ugly
while (! $driving) { // while not driving.
while ($driving == false) { // ugly
$drinking = ! $driving;
if ($driving && $drinking) {
Hence also use adjectives for boolean variables.
A condition is met, if the value or statement in it is considered as true.
The code $variable == true is a statement that looks whether the value of the variable is true and if it is, yields true - Or false if it is not.
However, as this means, that $variable itself can only ultimately be true or false, you don't even need the statement, as its return value will also be one of those two.
Therefore $variable is exactly the same as $variable == true.
I hope this made it clear.
The semantic of while/do-while is
while(<boolean expression>) {
// do your stuff
}
A boolean expression is anything that evaluates to true or false. So, if $loopCount is true, then $loopCount == true is checked on every loop and evalutes to true. But you could also write $LoopCount as condition, since it also evaluates to true.
This is very handy for using other data types, e.g. integers.
$count = 0;
while ($count < 10) {
$count = $count +1;
}
Here $count < 10 is a boolean expression that evaluates to true as long as $count is not higher then 9.
A while loop runs as long as the condition is met, in other words, as long as the boolean expression you provide evaluates to true.
You can also just use a variable, e.g. $loopCount when that variable evaluates to a boolean or a constant (even the constant value true).
Like Padarom said: Therefore $variable is exactly the same as $variable == true.
In your case: The while-do loop determines if redo the loop-body after the first run. Means the loop-body is executed exactly one time regardless what value $variable has. After the first run, the while($variable) checks if the expression is true. If so, the loop-body is executed second time and so forth.
Check PHP reference for do-while loops here. PHP.net do-while reference
while ($loopCond) and while ($loopCond == true) is the same thing. It checks the "trueness" of whatever you put in the brackets.
If I ask a question "does sun set in the west ? " what would be your answer, definitely YES OR TRUE. Same as compiler always look for statement value. Take a look
$condition = true;
if($condition == true )
// above will return TRUE; in short $condition == true will replaced by true at runtime. But if we place true directly which is $condition value or can say we place $condition instead true thus statement become shorten and look like...
if($condition) {
}

Multiple conditions in the ternary operator safe?

I have seen advice that says the ternary operator must not be nested.
I have tested the code below and it works okay. My question is, I haven't seen the ternary operator used like this before. So, is this as reliable as it were used in an if or could something like this come and bite me later(not in terms or readability, but by failing).
$rule1 = true;
$rule2 = false;
$rule3 = true;
$res = (($rule1 == true) && ($rule2 == false) && ($rule3 == true)) ? true : false;
if($res) {
echo "good";
} else {
echo "fail";
}
Thanks!
If the results you are returning from the ternary operator are only "true" and "false", then you don't even need the operator. You can just have:
$res = (($rule1 === true) && ($rule2 === false) && ($rule3 === true))
But, to answer your question, yes multiple conditions work perfectly well.
It's totally legal, it works and is "as reliable as if", but it looks ugly.
If you put each ternary statement inside parenthesis, nesting would be fine too:
$res = ( $rule1 ? true : ( $rule2 ? true : false ) )
The only thing that is advised against in the manual is nesting without parenthesis like this:
$res = ( $rule1 ? true : $rule2 ? true : false )
Is there a reason you want to have your conditions saved into a variable? this is the simplified version of above.
if($rule1 && !$rule2 && $rule3)
{
echo "good";
}
else
{
echo "bad";
}
You do not need the ternary if you are going to return true or false. Quoting the manual:
The expression (expr1) ? (expr2) : (expr3) evaluates to expr2 if expr1 evaluates to TRUE, and expr3 if expr1 evaluates to FALSE.
This means
$res = (($rule1 == true) && ($rule2 == false) && ($rule3 == true));
will assign true or false already. Also, if dont care about $rule being booleans, you dont need the comparison with ==. You also dont need the braces, e.g.
$res = $rule1 && !$rule2 && $rule3;
is the same as your initial ternary.
A good practise when you have multiple expressions like that is to hide the actual comparison behind a meaningful method or function name, e.g.
function conditionsMet($rule1, $rule2, $rule3) {
return $rule1 && !$rule2 && $rule3;
}
and then you can do
if (conditionsMet($rule1, $rule2, $rule3)) {
// do something
}
Of course, conditionsMet isnt that meaningful. A better example would be something like isSummerTime or isEligibleForDiscount and so on. Just express what the rules express in the method name.
You might also be interested in Simplifying Conditional Expressions from the book Refactoring - Improving the design of existing code.
You can also do
$res = ($rule1 && !$rule2 && $rule3);
It's legal and doesn't have to be "ugly". I use the "hook" operator often, in table form it's quite clean, e.g.:
bool haveANeed()
{
// Condition result
// ---------- ------
return needToEat() ? true
: needToSleep() ? true
: needToStudy() ? true
: needToShop() ? true
: needToThink() ? true
: false; // no needs!
}
This function would, IMHO, be less clear and certainly longer if written with if-else logic.

PHP: what's an alternative to empty(), where string "0" is not treated as empty? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Fixing the PHP empty function
In PHP, empty() is a great shortcut because it allows you to check whether a variable is defined AND not empty at the same time.
What would you use when you don't want "0" (as a string) to be considered empty, but you still want false, null, 0 and "" treated as empty?
That is, I'm just wondering if you have your own shortcut for this:
if (isset($myvariable) && $myvariable != "") ;// do something
if (isset($othervar ) && $othervar != "") ;// do something
if (isset($anothervar) && $anothervar != "") ;// do something
// and so on, and so on
I don't think I can define a helper function for this, since the variable could be undefined (and therefore couldn't be passed as parameter).
This should do what you want:
function notempty($var) {
return ($var==="0"||$var);
}
Edit: I guess tables only work in the preview, not in actual answer submissions. So please refer to the PHP type comparison tables for more info.
notempty("") : false
notempty(null) : false
notempty(undefined): false
notempty(array()) : false
notempty(false) : false
notempty(true) : true
notempty(1) : true
notempty(0) : false
notempty(-1) : true
notempty("1") : true
notempty("0") : true
notempty("php") : true
Basically, notempty() is the same as !empty() for all values except for "0", for which it returns true.
Edit: If you are using error_reporting(E_ALL), you will not be able to pass an undefined variable to custom functions by value. And as mercator points out, you should always use E_ALL to conform to best practices. This link (comment #11) he provides discusses why you shouldn't use any form of error suppression for performance and maintainability/debugging reasons.
See orlandu63's answer for how to have arguments passed to a custom function by reference.
function isempty(&$var) {
return empty($var) || $var === '0';
}
The key is the & operator, which passes the variable by reference, creating it if it doesn't exist.
if(isset($var) && ($var === '0' || !empty($var)))
{
}
if ((isset($var) && $var === "0") || !empty($var))
{
}
This way you will enter the if-construct if the variable is set AND is "0", OR the variable is set AND not = null ("0",null,false)
The answer to this is that it isn't possible to shorten what I already have.
Suppressing notices or warnings is not something I want to have to do, so I will always need to check if empty() or isset() before checking the value, and you can't check if something is empty() or isset() within a function.
function Void($var)
{
if (empty($var) === true)
{
if (($var === 0) || ($var === '0'))
{
return false;
}
return true;
}
return false;
}
If ($var != null)

Categories