Lesson Weekend

In this lesson, we're going to learn how to make more complex decisions in our code using three new symbols called logical operators:

  1. &&, called "and";
  2. ||, called "or";
  3. !, called "not".

Let's see what these are useful for by working on your fortune telling website from last lesson. Right now, here's how your function for getting a fortune based on your user's favorite color might look:

function tellFortuneFromColor($color)
{
    if ($color == "Red") {
        return "Your lucky number is 17.";
    }
    elseif ($color == "Orange") {
        return "You are about to find an excellent opportunity.";
    }
    elseif ($color == "Yellow") {
        return "You should go to the beach.";
    }
    elseif ($color == "Green") {
        return "You are a loyal and true friend.";
    }
    elseif ($color == "Blue") {
        return "You are going to be very wealthy.";
    }
    elseif ($color == "Violet") {
        return "You know that thing you are thinking of doing? Do it!";
    }
    else {
        return "I do not know that color.";
    }
}

Let's simplify it. Suppose you didn't feel like including a fortune for every single color and month - for example, it would be way easier to show one fortune if their favorite color is red, orange or yellow, and a different one for green, blue or violet. We can do this by rewriting the fortune teller using ||:

function tellFortuneFromColor($color)
{
    if ($color == "Red" || $color == "Orange" || $color == "Yellow") {
        return "Your lucky number is 17.";
    }
    elseif ($color == "Green" || $color == "Blue" || $color == "Violet") {
        return "You are a loyal and true friend.";
    }
    else {
        return "I do not know that color.";
    }
}

Now there are three possible forks in the road for our code to travel instead of seven. If the user has picked "Red", "Orange" or "Yellow", they will get the first fortune. If they have picked "Green", "Blue", or "Violet", then they will get a different fortune. If they type anything that doesn't match any of those six color options (like "Gray", or like "red" instead of "Red") then the function runs the "else" code as a fallback and says it doesn't recognize that color.

Let's start up our PHP shell and type in the shorter version of the function tellFortuneFromColor. Now test it with these commands:

> echo tellFortuneFromColor("Red");
Your lucky number is 17.
> echo tellFortuneFromColor("Orange");
Your lucky number is 17.
> echo tellFortuneFromColor("Yellow");
Your lucky number is 17.
> echo tellFortuneFromColor("Green");
You are a loyal and true friend.
> echo tellFortuneFromColor("Blue");
You are a loyal and true friend.
> echo tellFortuneFromColor("Violet");
You are a loyal and true friend.
> echo tellFortuneFromColor("Magenta");
I do not know that color.

As you can see, the symbol || works like the word or. If at least one condition, on either side of the ||, is true then the whole expression is true.

Let's try out the && operator with the || operator by making a function to calculate the price of your auto insurance. This insurance company charges the most money for customers who are under 25 years old and male. They charge the least amount of money if you are over 25 and female. They charge a median amount if you are either under 25 and female, or over 25 and male.

> function calculateInsurance($age, $gender)
{
    if ($age < 25 && $gender == "male") {
        return "This person is both young and male. Their insurance will be the most expensive.";
    } elseif ($age < 25 || $gender == "male") {
        return "This person is either young OR male. Their insurance is less expensive.";
    } else {
        return "This person is both over 25 and not male. Their insurance will be the cheapest.";
    }
}

Now we can plug in some numbers to see how this works.

> echo calculateInsurance(21, "male");
"This person is both young and male. Their insurance will be the most expensive."

Here we pass in the number 21 for $age and the word "male" for $gender. The condition to the left of the && next to the if is true because 21 is less than 25, and the condition to the right is true as well because "male" == "male". So, the whole statement is true because && requires both the values on its left and right to be true. Now try these:

> echo calculateInsurance(26, "male");
"This person is either young OR male. Their insurance is less expensive."
> echo calculateInsurance(21, "female");
"This person is either young OR male. Their insurance is less expensive."

These two examples end up in the elseif part of our code. Let's look at the first one. In the if part, 26 is not less than 25, so the condition to the left of the && is false. Therefore, the whole statement with the && is false because if one of the &&'s conditions is false, you already know that both are not true.

So our code travels downward to the elseif to see if that statement is true or not. Since 26 is more than 25, the condition on the left of the || is false, but the condition on the right is true, so the whole || statement is true and its code is executed. The same thing happens on the next function call. Only one of the conditions $age < 25 and $gender == "male" is true, so the if's && statement does not pass, but the elseif's || statement does.

Let's try one more.

> echo calculateInsurance(26, "female");
"This person is both over 25 and not male. Their insurance will be the cheapest."

Neither of our conditions are true here. The age is over 25 and the gender is female, so neither the && or the || statements are true. So our code continues to travel downward, and the only other alternative is to execute the code next to else, giving this user the cheapest insurance.

Let's try out our last logical operator, !, which is pronounced not. First, let's take a look at a branch without !:

> if (5 > 6) {
       echo "It is true that 5 is greater than 6.";
   } else {
       echo "It is false that 5 is greater than 6.";
   }
It is false that 5 is greater than 6.

Now, let's see how ! works:

> if (!(5 > 6)) {
       echo "It is true that 5 is not greater than 6.";
   } else {
       echo "It is false that 5 is not greater than 6.";
   }
It is true that 5 is not greater than 6.

Putting the ! before a condition reverses it, in the same way that != is the opposite of ==.

Remember that there always has to be a set of parenthesis after the keywords if and elseif, so put the ! inside there with another set of parenthesis next to the ! symbol, holding the condition that you want to reverse.

Let's look at another example.

> if ("cat" == "cat") {
       echo "It is true that a cat is a cat.";
   } else {
       echo "It is false that a cat is a cat.";
   }
It is true that a cat is a cat.

> if (!("cat" == "cat")) {
       echo "It is true that a cat is not a cat.";
   } else {
       echo "It is false that a cat is not a cat.";
   }
It is false that a cat is not a cat.

The condition in the innermost parentheses is evaluated first. Then ! will reverse its value. "cat" is equal to "cat", but "cat" is NOT equal to "cat" is false.

Let's use a couple of these operators together to set up a concert for your favorite band: The Fictionals! You have your people talk to their people and you find out that they have some requirements. They will only play if you pay them their guarantee of $2000, and they are a very superstitious band who refuses to play on Thursdays. Let's write a function to figure out if they can play or not. Enter this into the shell:

> function canPlay($money, $day_of_the_week)
{
    if($money >= 2000 && (!($day_of_the_week == "Thursday"))){
        return "Hooray! The band can play!";
    }
    else {
        return "Aw man, gotta find someone else.";
    }
}

This function says that the band can play if we have at least $2000 it isn't a Thursday. Now let's try it out:

> echo canPlay(2000, "Friday");
Hooray! The band can play!
> echo canPlay(3000, "Thursday");
Aw man, gotta find someone else.
> echo canPlay(1000, "Saturday");
Aw man, gotta find someone else.

In our first example we see that they can play if we pay them $2000 and book it for a Friday. But in our second example we see that they won't play on Thursday, even if we pay them $3000, because both conditions on either side of the && have to be true for our if statement to be true. In the same way, the last example shows us that they would be fine with playing on Saturday, but not for only $1000.

The condition $day_of_the_week == "Thursday" evaluates to true on Thursdays. But if we change it by using the ! before it then that whole condition evaluates to true on every day except for Thursdays.