Why doesn't this if test work? - php

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

Related

If statement with && and multiple OR conditions in PHP

I'm having trouble trying to make the statement below work the way I want it to.
I am trying to display an error message for an order form if at least one text field is not filled out. Below is a snippet of my PHP code. The 'cookieGiftBox' is the name of a checkbox that users can select and if it is selected, they must enter an amount of cookies under their desired flavors in the text fields provided. How can I display an error message to display when the checkbox IS selected but NO text fields have been filled out?
<?php
if (isset($_POST['cookieGiftBox'])
&& (!isset($_POST['sugar'])
|| ($_POST['chocolateChip'])
|| ($_POST['chocolateChipPecan'])
|| ($_POST['whiteChocolateRaspberry'])
|| ($_POST['peanutChocolateChip'])
|| ($_POST['peanutButter'])
|| ($_POST['tripleChocolateChip'])
|| ($_POST['whiteChocolateChip'])
|| ($_POST['oatmealRaisin'])
|| ($_POST['cinnamonSpice'])
|| ($_POST['candyChocolateChip'])
|| ($_POST['butterscotchToffee'])
|| ($_POST['snickerdoodle']))) {
$error.="<br />Please enter an Amount for Cookie Flavors";
}
?>
&& takes precedence over ||, thus you would have to use parentheses to get the expected result:
if (isset($_POST['cookieGiftBox']) && (!isset($POST['sugar']) || ...)
Actually, to get check if nothing is selected, you would do something like this:
if checkbox is checked and not (sugar is checked or chocolatechip is checked) or the equivalent:
if checkbox is checked and sugar is not entered and chocolatechip is not entered....
If you want to know more, search for information about Boolean algebra.
Update: In your example and in the correct syntax the sentence I took as an example would like this (for the first sentence, note the not (!) and the parentheses around the fields, not the checkbox):
if (isset($_POST['cookieGiftBox']) &&
!(
isset($_POST['sugar']) ||
isset($_POST['chocolatechip'])
)
) { error ...}
Or the second sentence, which might be easier to understand (note the && instead of ||):
if (isset($_POST['cookieGiftBox']) &&
!isset($_POST['sugar']) &&
!isset($_POST['chocolatechip'])
) { error...}
Using ands makes sure it is only true (and thus showing the error) if none of the sugar, chocolatechips, etc. fields are set when the giftbox checkbox is checked.
So if the checkbox is checked, and no fields are set it looks like this:
(true && !false && !false) which is equivalent to (true && true && true) which is true, so it shows the error.
If the checkbox is checked and sugar is entered it would look like this:
(true && !true && !false), equ. to (true && false && true), equ. to false and thus no error is shown.
If both sugar and chocolatechip are entered also no error will be shown.
I have simillar issue:
I try use:
if (isset($this->context->controller->php_self) && ($this->context->controller->php_self != 'category') || ($this->context->controller->php_self != 'product') || ($this->context->controller->php_self != 'index')){ ... }
Thats didn't work, I change it to:
if (isset($this->context->controller->php_self) && ($this->context->controller->php_self != 'category') && ($this->context->controller->php_self != 'product') && ($this->context->controller->php_self != 'index')){ ... }
I dont know it is correct?
Edit. This is not correct, but for now i didnt know how to fix it.

Display HTML if two conditions are true or another two are true or third part of conditions are true

I have php if statement that should display certain HTML code if two conditions are true or another two are true or third part of conditions are true.
I have several arrays - $Options_arr, $MoreOptions_arr, $Special_arr .
To explain in the easiest possible way I want to do this:
if(!empty($Options_arr[0]) && $Options_arr[0]!="") or
(!empty($MoreOptions_arr[0]) && $MoreOptions_arr[0]!="") or
(!empty($Special_arr[0]) && $Special_arr[0]!="")
{?> some HTML here
All help will be appreciated thank you.
empty() already checks for empty string "" so it's shorter:
if(!empty($Options_arr[0]) || !empty($MoreOptions_arr[0]) || !empty($Special_arr[0])) {
//some HTML here
}
BragG, you can use elseif
Like:
if((!empty($Options_arr[0]) && $Options_arr[0]!="") ||
(!empty($MoreOptions_arr[0]) && $MoreOptions_arr[0]!="") ||
(!empty($Special_arr[0]) && $Special_arr[0]!=""))
{
// some html or any code
}
I hope that is what you were looking for..
Feel free to ask any question.
You are just missing some brackets. Also || is more frequently used than OR
if((!empty($Options_arr[0]) && $Options_arr[0]!="") || (!empty($MoreOptions_arr[0]) && $MoreOptions_arr[0]!="") || (!empty($Special_arr[0]) && $Special_arr[0]!="")){
echo '<p>hello</p>';
}
You're basically already there...
if (
(!empty($Options_arr[0]) && $Options_arr[0]!="")
|| (!empty($MoreOptions_arr[0]) && $MoreOptions_arr[0]!="")
|| (!empty($Special_arr[0]) && $Special_arr[0]!="")
){
...do something
Basically you write an if statement that resolves if any of the sub-statements are true by joining the sub-statements together with ORs

Not operator with multiple or operator

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.

Can't view a message through php?

Okay, I have a php code for my mail.php, so that if the current user id doesn't match the to or from id, it will show an error message, but I tested it out and any use can view the message, here's the code :
if (!$mail['to_id'] == $account['id'] && !$mail['from_id'] == $account['id']) {
$system->message(L_ERROR, L_MAIL_ERROR_PERMISSION, './?area=forum&s=mail', L_CONTINUE);
}
But when I added != instead of ==, it shows an error message for everyone, including the people who sent the message. Does anyone know how I can fix this problems?
Use this code instead.
if ($mail['to_id'] != $account['id'] && $mail['from_id'] != $account['id']) {
$system->message(L_ERROR, L_MAIL_ERROR_PERMISSION, './?area=forum&s=mail', L_CONTINUE);
}
Your logic is:
!$mail['to_id'] == $account['id']
&&
!$mail['from_id'] == $account['id']
The problem stems from doing this:
!$mail['to_id']
and
!$mail['from_id']
The inverse operator (!) flips the value of what it's being applied to. In this case, you're flipping the value of $mail ID's. That's probably not going to do what you're thinking since those ID's, I'm assuming, are integers.
It might help to think of this in the positive and then reverse the whole thing.
The positive is:
$mail['to_id'] == $account['id']
&&
$mail['from_id'] == $account['id']
The inverse of it is wrapping the whole thing in a "!" (note the parenthesis):
!(
$mail['to_id'] == $account['id']
&&
$mail['from_id'] == $account['id']
)
We can use the rules of Algebra to convert that statement by multiplying "!" against each element (including the AND operator).
!($mail['to_id'] == $account['id']) // Note you apply the inverse of to the whole expression
!&& // this isn't an actual code but for demonstration purposes
!($mail['from_id'] == $account['id']) // Note you apply the inverse of to the whole expression
Which simplifies into:
$mail['to_id'] != $account['id'] // Not Equal is inverse of equal
|| // the inverse of && (AND) is || (OR)
$mail['from_id'] != $account['id'] // Not Equal is inverse of equal
Which states:
"If the Mail_To OR Mail_From ID doesn't match the Account ID, execute the following code"
So, at the end of the day you should be able to use:
if( $mail['to_id'] != $account['id'] || $mail['from_id'] != $account['id'] )
{
// do something
}
or
if( !( $mail['to_id'] == $account['id'] && $mail['from_id'] == $account['id']) )
{
// do something
}
Both say the same thing.
I hope that helps!

PHP Conditional logic, specific order?

I have a conditional statement which goes thusly:
if ($_POST['password'] == $_POST['repeat'] && $_SESSION['type'] == "admin")
But let's say I also want the conditional to evaluate true to users with type "superuser" (instead of "admin").
So I could, for example, write:
if ($_POST['password'] == $_POST['repeat'] && $_SESSION['type'] == "admin" || $_SESSION['type'] == "superuser")
But assuming PHP reads conditionals and equations from the left to the right, it's then possible for a "superuser" to have the conditional evaluate true even if "password" and "repeat" are not equal, since we're placing imaginary brackets around the two operands next to "&&", right?
I could add brackets to encapsulate the two operands for "||", but I recall faintly that I may have tried something in the past, and had it fail spectacularly.
Is there a better way to do this? Do brackets actually work (thus concluding that my memory is faulty? [memory leak? heh.])
Thanks!
Yes, parentheses will override the fact that && has a higher precedence than ||.
Haven't tested but try this:
if ($_POST['password'] == $_POST['repeat'] &&
($_SESSION['type'] == "admin" || $_SESSION['type'] == "superuser"))
Enclose the admin check in () and OR the 'type' check. Superuser should get checked first for optimal code.
($_SESSION['type'] == "superuser" || ($_POST['password'] == $_POST['repeat'] && $_SESSION['type'] == "admin") )
To get what you want you could:
if (($_POST['password'] == $_POST['repeat']) && ($_SESSION['type'] == "admin" || $_SESSION['type'] == "superuser"))
Which would evaluate to true when passwords match and if the user type is admin or super user.
Or, more verbosely:
$valid_password= $_POST['password'] == $_POST['repeat'];
$valid_user= $_SESSION['type'] == "admin" || $_SESSION['type'] == "superuser";
if ($valid_password && $valid_user)
// Do something

Categories