Not operator with multiple or operator - php

I am confuse with bellow code:
Fist code that is not working:
if ($_SESSION['userType'] != 'A' || $_SESSION['userType'] != 'S')
{
redirect('dashboard.php');
}
Second code that is working:
if (!($_SESSION['userType'] == 'A' || $_SESSION['userType'] == 'S'))
{
redirect('dashboard.php');
}
What is difference between both code?

I know you already have six answers to your question, but none of them uses plain English, so I'll make an attempt myself as well.
Let's look at this code step by step, splitting it up into smaller portions, and explaining each step exactly.
Code that isn't working
First you have this row:
if ($_SESSION['userType'] != 'A' || $_SESSION['userType'] != 'S')
Instead of looking at the full if clause already, let's divide it into two parts:
if ($_SESSION['userType'] != 'A')
if ($_SESSION['userType'] != 'S')
The first part will trigger any time that $_SESSION['userType'] is any value other than A.
The second part will trigger any time that $_SESSION['userType'] is any value other than S.
Now, you've joined them both together with an "or" operator, so that it's enough that one of them is true for the if clause to trigger. Let's see what happens when we try it out.
We set $_SESSION['userType'] to 'B' and go into the if clause. The first thing that happens is that PHP looks at the first part, if ($_SESSION['userType'] != 'A'), and finds that 'B' != 'A'. It doesn't need to go to the second part, because it already found that one of the parts of the if statement is true, and so it decides that the full if statement must also be true.
We set $_SESSION['userType'] to 'A' and go into the if clause. The first thing that happens is that PHP looks at the first part, if ($_SESSION['userType'] != 'A'), and finds that 'A' == 'A', so the first part is false. It then goes on to the second part, which is if ($_SESSION['userType'] != 'S'), and finds that 'A' != 'S'. Since this means that one of the parts of the if statement is true, it again decides that the full if statement must also be true.
Now notice what this means. Even if you send an 'A' to the if clause, it will still trigger because of the second part. And if you were to send an 'S', it will trigger because of the first part. So essentially, the full first if statement will trigger regardless of what $_SESSION['userType'] is set to. It's a tautology - it's always true.
Code that is working
This is your full if statement:
if (!($_SESSION['userType'] == 'A' || $_SESSION['userType'] == 'S'))
Let's ignore the ! for now, and divide it into the two parts of the or operator.
if ($_SESSION['userType'] == 'A')
if ($_SESSION['userType'] == 'S')
Notice that this is the logical opposite of the code you had that didn't work. The first row means "only accept an 'A'" and the second means "only accept an 'S'". So this code will trigger only if you give it either an 'A', or an 'S'.
Now, what happens if you put an ! in front of the whole thing, like you did?
The ! operator simply reverses whatever it is put in front of. So this changes the meaning from "either A or S" to "neither A nor S".
Summary
Your first example comes down to "any value whatsoever".
Your second example comes down to "any value, but not A, and also not S".
If you want to learn more of basic logic, I suggest looking at De Morgan's laws, as you were linked to in an above comment. This will give you an understanding of how and and or fits together.

Not...quite.
If I remember boolean logic correctly, the fault lies in order of operations.
if ($_SESSION['userType'] != 'A' || $_SESSION['userType'] != 'S') {
if userType equals A, this will not work...since the first operation is to check that it is not equal to A and ORs are left to right...so if the first is not true, the entire statement is false.
Your second approach translates to:
if (!($_SESSION['userType'] == 'A' || $_SESSION['userType'] == 'S'))
{
redirect('dashboard.php');
}
IF NOT userType equals A OR userType equals S which is why it works as you desire it to.
Try
if ($_SESSION['userType'] != 'A' && $_SESSION['userType'] != 'S')) {
which means IF userType is not A and userType is not S
I think that will give you what you are probably looking for. IE Only do what is in the loop if the userType is neither A, nor S.

if ($_SESSION['userType'] != 'A' || $_SESSION['userType'] != 'S') {
is more or less equivalent to
if (!($_SESSION['userType'] == 'A' && $_SESSION['userType'] == 'S')) {

first code that is not working
if ($_SESSION['userType'] != 'A' || $_SESSION['userType'] != 'S')
{
redirect('dashboard.php');
}
lets simplyfy it as under:
if (true || true) //the condition will be true or vice versa
{
redirect('dashboard.php');
}
Second code that is working:
if (!($_SESSION['userType'] == 'A' || $_SESSION['userType'] == 'S'))
{
redirect('dashboard.php');
}
and the simplified version:
if (!(true || true)) same as if (!(true)) //i.e. false or vice versa
{
redirect('dashboard.php');
}
so basically one is true and the other is false or vice versa so thats why they are acting diffrenetly.

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...')))

How to use an IF statement to ensure one is always true, and either of the others is true

I am trying to do this in a single IF statement to avoid having duplicated code, I would like to know if it is possible to do what I want to do.
I originally had this code to run code on all categories that doesn't equal '15', Now I need it to not apply to categories 15 and 57.
Original code:
if ($level==1 && $category_id!=15){
New code (the general idea):
if ($level==1 && ($category_id!=15 || $category_id!=57)){
Edit: If downvoting, please explain why. I have tested the code above and it always returns false.
The following code means that if will be true when $level equals to 1 and $category_id doesn't equal to none of 15, 57.
if ($level == 1 && !in_array($category_id, array(15, 57)))
Have a look here: in_array
It should be:
if ($level==1 && $category_id!=15 && $category_id!=57){
You can just use multiple and criteria:
if ($level==1 && $category_id!=15 && $category_id!=57){
The reason your current code fails (it will always return true when $level==1) is because $category_id can never be both values.
let $category_id ==15 then the left side of the condition ($category_id!=15 || $category_id!=57) will evaluate to false (15 != 15) == false so the right side will be evaluated (15 != 57) == true causing the overall statement to evaluate to true.
let $category_id ==57 then the left side of the condition ($category_id!=15 || $category_id!=57) will evaluate to true (57 != 15) == true so the right side is never evaluated, causing the overall statement to evaluate to true.

Comparing equality to one of multiple values [duplicate]

This question already has answers here:
PHP If Statement with Multiple Conditions
(11 answers)
Closed 9 years ago.
I'm passing values on a url to a page on my site. So when a user clicks a link different values will pass to the new page depending on which link they click. I'm using a conditional on the second page to vary the code that gets run depending on the value in $_GET.
Unfortunately, for reasons unknown to me the conditionals don't seem to be working properly. In the if statements I'm using || because there are multiple passed values that need to trigger the same code on the second page (they need to be named differently because they also all trigger unique code).
It seems rather simple, I start with:
if($_GET['id']=('x' || 'y' || 'z')) {
block of code
}elseif($_GET['id']=('a' || 'b' || 'c')) {
block of code
}else{
block of code
}
I have printed out the values of the $_GET['id'] to check that the correct value is being passed from the first page to the second based on the link clicked. This is working properly. Every link I click prints the expected value. The odd thing is I echo'd these values both within the first conditional and above it. It printed in both cases, even when it printed a value that shouldn't have triggered that conditional. Any ideas?
The syntax you're using for checking if $_GET['id'] is one of the valid values in the set is wrong.
I think you mean to be doing something more like this:
<?php
if (in_array($_GET['id'], array('x', 'y', 'z') {
/* block 1*/
}
else if (in_array($_GET['id'], array('a', 'b', 'c')) {
/* block 2 */
}
else {
/* block 3 */
}
Some further information on the code you did write:
It's passing because the syntax is valid, but not for what you want to do.
Essentially you're saying "Assign $_GET['id'] to the first truthy value of 'a', 'b', or 'c'." The problem there is, all strings (unless they are "0") are evaluated as true.
Furthermore, the single equals symbol (=) assigns the value to the variable and evaluates as true (the assignment was successful). So you're always setting $_GET['id'] to the first string in ('a' || 'b' || 'c'). Therefore, you're assigning $_GET['id'] and it's evaluating to true so the first if condition is always met.
if($_GET['id'] == 'x' || $_GET['id'] == 'y' || $_GET['id'] == 'z') {
block of code
}elseif($_GET['id'] == 'a' || $_GET['id'] == 'b' || $_GET['id'] == 'c') {
block of code
}else{
block of code
}
I think you can also use switch statement. Like the following
$value = 'x'; // $_GET['id']
switch($value) {
//matches if one or more case is met
case 'x':
case 'y':
case 'z':
echo 'i am x, y or z';//here your block code
break;
//matches if one or more case is met
case 'a':
case 'b':
case 'c':
echo 'i am x, y or z';//here your block code
break;
default:
echo 'I have no value';
}

PHP operators if statement 'and' and 'or'

I have an if statement that I want to control with having one field needing input and they have to pick one of the other 2 choices.
if(test1 && test || test3){
//Something here
}
Should I do it like this:
if(test1 && (test2 || test3)){
//do stuff
}
How would I go about doing this. I can't wrap my head around the logic...
if ($requiredField && ($optional1 || $optional2)) {
/* Do something */
}
For the /* Do something */ bit of code to be executed, the if statement has to evaluate to TRUE.
This means, that $requiredField must be TRUE, and so must be ($optional1 || $optional2).
For $requiredField to be TRUE, it just needs to be filled in - and for the second part: ($optional1 || $optional2) either optional1 or optional2 would do it.
Edit:
After rereading the question, it seems that I might have misunderstood you. If the user must enter one specific piece of information, and must choose only one (not both) out of two options - then the following should be used.
if ($requiredField && ($optional1 ^ $optional2)) {
/* Do something */
}
This means that $optional1 or $optional2 must be filled out - but not both of them.
From the sound of it, you want the latter:
if ($test1 && ($test2 || $test3)){
//do stuff
}
Think of it as two conditions needing to be met. This gives you those two conditions. The second condition just happens to be another condition. The first option you posted, however, is quite the opposite as it can allow execution if just $test3 is true
test1 && (test2 || test3) is very easy to understand from the first place - Choose test1 && (test2 || test3) means one the last two. Very clear.
test1 && test || test3 - doesn't seem to be correct:
test1 = false
test2 = false
test3 = true
false && false || true = true
doesn't actually fit your criteria.
... they have to pick one of the other 2 choices
I'm just throwing a guess out here. If you really want to ensure that one, but only one of the two other options are selected, then you need xor:
if ($required AND ($and_either XOR $or_other)) {
You can have 'nested' if statements withing a single if statement, with additional parenthesis.
if(test1 && (test2 || test3)){
//do stuff
}
Your logic is right but your sintax isnt, you should compare the values of the variables as show, or simply ignore them as saying you are trying to compare them as they are TRUE.
$test1=true;
$test2=true;
$test3=false;
if($test1==true && ($test2==true || $test3==true){ echo "YES";}
This will output YES.

Why doesn't this if test work?

My site requires a login that establishes permissions based on the user. In the photo listing of the site, I must determine if a particular photo will be displayed if the user has guest access only. So I thought that this if else statement would work:
if (!($mysql_row['guest_access'] == 'NO') AND ($_SESSION['user_level'] == 'GUEST')) {
// show the photo if it isn't private and the user isn't a guest
But it doesn't.
However, if I separate this test into three lines then it works just fine.
$is_private_photo = $mysql_row['guest_access'] == 'NO';
$is_guest = $_SESSION['user_level'] == 'GUEST';
$both_private_and_guest = ($is_private_photo AND $is_guest);
if (!$both_private_and_guest) {
// show the photo if it isn't private and the user isn't a guest
What is wrong with the first version?
Your first if is
if (!($mysql_row['guest_access'] == 'NO') AND ($_SESSION['user_level'] == 'GUEST'))
Which is actually interpreted like this :
if (
(!($mysql_row['guest_access'] == 'NO'))
AND ($_SESSION['user_level'] == 'GUEST')
)
The ! is only applied to the first condition, not both, because it has a higher level of priority than AND (see Operator Precedence)
Your condition should probably be re-written with some additional parentheses :
if (!(($mysql_row['guest_access'] == 'NO') AND ($_SESSION['user_level'] == 'GUEST')))
So the ! is applied to the whole condition.
The logical not operation needs to be applied to the AND results, but in your code sample it only applied to the first clause (NOT has higher precedence than AND). You can solve it by grouping both conditions:
if (!(($mysql_row['guest_access'] == 'NO' AND ($_SESSION['user_level'] == 'GUEST'))) {
The not operator (!) only covers the first condition so either add another bracket, or do this
if ( $mysql_row['guest_access'] != 'NO' AND...
It's because you put the parentheses in the wrong place in your first version. The equivalent form of the second version is
if (!$is_private_photo AND $is_guest)
which is clearly not what you intended.
Make it like this:
if (($mysql_row['guest_access'] != 'NO') AND ($_SESSION['user_level'] != 'GUEST')) {
Your '!' is not being applied to the 'AND' statement...it is only being applied to the ($mysql_row['guest_access'] == 'NO') statement.
You are only negating the first condition. Try this:
if (!($mysql_row['guest_access'] == 'NO' AND $_SESSION['user_level'] == 'GUEST')) {
Your negation operator does not apply as expected. You should use something like:
if ( ! (($mysql_row['guest_access'] == 'NO') AND ($_SESSION['user_level'] == 'GUEST')) )
if ( ! ($mysql_row['guest_access'] == 'NO') OR ! ($_SESSION['user_level'] == 'GUEST') )

Categories