Skip to main content

โš™๏ธ Lesson 4: Operators & Expressions

Operators are the verbs of programming โ€” they do things to your data. In this lesson, you'll learn every operator you need to write meaningful PHP programs.

๐ŸŽฏ Learning Objectives

By the end of this lesson, you will be able to:

  • Perform arithmetic, string, and assignment operations
  • Use comparison operators (including the difference between == and ===)
  • Combine conditions with logical operators
  • Write concise code with the ternary and null coalescing operators
  • Predict evaluation order using operator precedence rules

Estimated Time: 40 minutes

Prerequisites: Lesson 3 (variables, data types)

๐Ÿ“‘ In This Lesson

What Are Operators and Expressions?

๐Ÿ“– Definitions

Operator: A symbol that performs an operation on one or more values (called operands).

Expression: Any combination of values, variables, operators, and function calls that PHP can evaluate to produce a result.

<?php
//    operand  operator  operand
//       โ†“        โ†“        โ†“
$result = 10      +        5;       // Expression: 10 + 5 evaluates to 15

// Everything that produces a value is an expression:
$x = 42;              // 42 is an expression
$y = $x * 2;          // $x * 2 is an expression
$z = strlen("hello"); // strlen("hello") is an expression

PHP groups operators into several categories. Let's work through each one.

Arithmetic Operators

These work exactly like math class โ€” with a couple of programming-specific additions.

Operator Name Example Result
+ Addition 10 + 3 13
- Subtraction 10 - 3 7
* Multiplication 10 * 3 30
/ Division 10 / 3 3.3333...
% Modulo (remainder) 10 % 3 1
** Exponentiation 2 ** 8 256
- Negation (unary) -$x Negative of $x
<?php
$a = 17;
$b = 5;

echo $a + $b;   // 22
echo $a - $b;   // 12
echo $a * $b;   // 85
echo $a / $b;   // 3.4
echo $a % $b;   // 2  (17 divided by 5 = 3 remainder 2)
echo $a ** $b;  // 1419857  (17 to the power of 5)

Division Details

<?php
// Division of two integers that divides evenly โ†’ integer result
var_dump(10 / 2);    // int(5)

// Division that doesn't divide evenly โ†’ float result
var_dump(10 / 3);    // float(3.3333...)

// Integer division (discard remainder) โ€” use intdiv()
var_dump(intdiv(10, 3));  // int(3)

โš ๏ธ Division by Zero

Dividing by zero throws a DivisionByZeroError in PHP 8. Always check before dividing:

$denominator = 0;
if ($denominator !== 0) {
    echo 100 / $denominator;
} else {
    echo "Cannot divide by zero!";
}

Common Uses for Modulo (%)

Modulo is more useful than it first appears:

<?php
// Check if a number is even or odd
$num = 42;
if ($num % 2 === 0) {
    echo "$num is even";   // This runs
}

// Cycle through values (e.g., alternating row colors)
for ($i = 0; $i < 6; $i++) {
    $class = ($i % 2 === 0) ? "even-row" : "odd-row";
    echo "<tr class='$class'>Row $i</tr>\n";
}

// Check if a number is divisible by another
$year = 2024;
$isLeapYear = ($year % 4 === 0 && $year % 100 !== 0) || ($year % 400 === 0);
// true โ€” 2024 is a leap year

Increment and Decrement

<?php
$count = 10;

// Pre-increment: increment, THEN return the value
echo ++$count;  // 11 (increments first, then outputs 11)

// Post-increment: return the value, THEN increment
$count = 10;
echo $count++;  // 10 (outputs 10, then increments to 11)
echo $count;    // 11

// Same idea for decrement
$count = 10;
echo --$count;  // 9  (pre-decrement)
$count = 10;
echo $count--;  // 10 (post-decrement, $count is now 9)

โœ… Practical Rule

If you just need to add or subtract 1 and don't care about the return value, $count++ and ++$count do the same thing. The distinction only matters when you use the result inline (like in an echo or array index).

Assignment Operators

The basic assignment operator is =. PHP also has compound assignment operators that combine an operation with assignment:

Operator Example Equivalent To Description
= $x = 5 โ€” Assign
+= $x += 3 $x = $x + 3 Add and assign
-= $x -= 3 $x = $x - 3 Subtract and assign
*= $x *= 3 $x = $x * 3 Multiply and assign
/= $x /= 3 $x = $x / 3 Divide and assign
%= $x %= 3 $x = $x % 3 Modulo and assign
**= $x **= 2 $x = $x ** 2 Exponent and assign
.= $s .= " world" $s = $s . " world" Concatenate and assign
??= $x ??= 10 $x = $x ?? 10 Assign if null
<?php
$score = 100;
$score += 25;    // $score is now 125
$score -= 10;    // $score is now 115
$score *= 2;     // $score is now 230

$message = "Hello";
$message .= ", ";     // "Hello, "
$message .= "World!"; // "Hello, World!"

echo $message;   // Hello, World!
echo $score;     // 230
๐Ÿ’ก Tip: The .= (concatenate-assign) operator is incredibly common in PHP โ€” you'll use it anytime you build up a string piece by piece, like constructing HTML output.

String Operators

PHP has just two string operators, but you'll use them constantly:

Operator Name Example Result
. Concatenation "Hello" . " " . "World" "Hello World"
.= Concatenation assignment $s .= "!" Appends to $s
<?php
$firstName = "Alice";
$lastName = "Johnson";

// Concatenation โ€” joining strings together
$fullName = $firstName . " " . $lastName;
echo $fullName;  // Alice Johnson

// Building HTML with concatenation
$html = "<div class='user-card'>";
$html .= "<h3>" . $fullName . "</h3>";
$html .= "<p>Member since 2024</p>";
$html .= "</div>";
echo $html;

โš ๏ธ The + Operator Does NOT Concatenate Strings

Unlike JavaScript, PHP's + is always arithmetic. If you use + on strings, PHP type-juggles them to numbers:

echo "Hello" + " World";   // 0 (both become 0, then 0 + 0 = 0)
echo "5" + "3";             // 8 (not "53"!)
echo "5" . "3";             // "53" (concatenation โ€” this is what you want)

Comparison Operators

Comparison operators compare two values and return a boolean (true or false). They're essential for making decisions in your code.

Operator Name Example Result
== Equal (loose) "5" == 5 true
=== Identical (strict) "5" === 5 false
!= Not equal (loose) "5" != 5 false
!== Not identical (strict) "5" !== 5 true
< Less than 3 < 5 true
> Greater than 3 > 5 false
<= Less than or equal 5 <= 5 true
>= Greater than or equal 5 >= 3 true
<=> Spaceship 1 <=> 2 -1

== vs. === (Revisited)

We covered this in Lesson 3, but it's worth repeating because it's that important:

<?php
// Loose comparison (==) โ€” type juggling happens
var_dump(1 == "1");      // true โ€” string "1" becomes int 1
var_dump(0 == "");       // true โ€” both become 0/false
var_dump(null == false);  // true โ€” both are falsy
var_dump("" == false);    // true โ€” empty string is falsy

// Strict comparison (===) โ€” no type juggling
var_dump(1 === "1");     // false โ€” int vs string
var_dump(0 === "");      // false โ€” int vs string
var_dump(null === false); // false โ€” null vs bool
var_dump("" === false);   // false โ€” string vs bool

โœ… Rule of Thumb

Default to === and !==. Only use == when you specifically want type juggling โ€” and even then, think twice.

The Spaceship Operator (<=>)

The spaceship operator (PHP 7+) performs a three-way comparison. It returns -1, 0, or 1:

<?php
echo 1 <=> 2;   // -1 (left is less)
echo 2 <=> 2;   //  0 (equal)
echo 3 <=> 2;   //  1 (left is greater)

// Most useful for sorting
$prices = [29.99, 9.99, 49.99, 19.99];
usort($prices, function($a, $b) {
    return $a <=> $b;  // Sort ascending
});
// $prices is now [9.99, 19.99, 29.99, 49.99]

// For descending, swap $a and $b:
usort($prices, function($a, $b) {
    return $b <=> $a;  // Sort descending
});

Logical Operators

Logical operators combine boolean expressions. They're the glue that holds complex conditions together.

Operator Name Example Result
&& AND true && false false
|| OR true || false true
! NOT !true false
and AND (low precedence) true and false false
or OR (low precedence) true or false true
xor XOR (exclusive or) true xor true false

Truth Tables

graph LR subgraph "AND (&&)" A1["T && T = T"] A2["T && F = F"] A3["F && T = F"] A4["F && F = F"] end subgraph "OR (||)" B1["T || T = T"] B2["T || F = T"] B3["F || T = T"] B4["F || F = F"] end subgraph "XOR" C1["T xor T = F"] C2["T xor F = T"] C3["F xor T = T"] C4["F xor F = F"] end

Practical Examples

<?php
$age = 25;
$hasID = true;
$isMember = false;

// AND โ€” both conditions must be true
if ($age >= 21 && $hasID) {
    echo "Entry allowed";  // This runs
}

// OR โ€” at least one condition must be true
if ($isMember || $age >= 18) {
    echo "Can register";   // This runs (age condition is true)
}

// NOT โ€” inverts the boolean
if (!$isMember) {
    echo "Not a member yet"; // This runs
}

// Combining operators
$isAdmin = false;
$isEditor = true;
$isPublished = true;

if (($isAdmin || $isEditor) && $isPublished) {
    echo "Can view article"; // This runs
}

Short-Circuit Evaluation

PHP's logical operators are short-circuit โ€” they stop evaluating as soon as the result is determined:

<?php
// AND (&&): if the left side is false, PHP skips the right side
$x = false;
$result = $x && expensiveFunction(); // expensiveFunction() NEVER runs

// OR (||): if the left side is true, PHP skips the right side
$x = true;
$result = $x || expensiveFunction(); // expensiveFunction() NEVER runs

// This is useful for guard clauses:
if (isset($user) && $user->isActive()) {
    // $user->isActive() only runs if $user exists
    // Without short-circuiting, this could crash
}

โš ๏ธ and/or vs. &&/||

The word forms (and, or) have lower precedence than the symbol forms (&&, ||). This can cause surprising behavior:

// These are NOT the same:
$result = true || false && false;
// Evaluates as: true || (false && false) โ†’ true

$result = true or false && false;
// Evaluates as: ($result = true) or (false && false)
// $result is true, but for the wrong reason!

// Best practice: always use && and ||

The Ternary Operator

The ternary operator is a compact way to write simple if/else statements. It's called "ternary" because it takes three operands.

Basic Syntax

$result = (condition) ? valueIfTrue : valueIfFalse;
<?php
$age = 20;

// Instead of this:
if ($age >= 18) {
    $status = "adult";
} else {
    $status = "minor";
}

// You can write this:
$status = ($age >= 18) ? "adult" : "minor";
echo $status; // "adult"

Common Use Cases

<?php
// Setting defaults
$name = isset($_GET['name']) ? $_GET['name'] : "Guest";

// Conditional CSS classes
$rowClass = ($index % 2 === 0) ? "even" : "odd";
echo "<tr class='$rowClass'>";

// Pluralization
$count = 5;
$label = ($count === 1) ? "item" : "items";
echo "$count $label";  // "5 items"

// Display logic
$score = 85;
$grade = ($score >= 90) ? "A" : (($score >= 80) ? "B" : "C");
echo $grade; // "B"

โš ๏ธ Don't Nest Too Deep

Nested ternaries become unreadable fast. If you need more than one level of nesting, use an if/elseif block instead. PHP 8 actually requires parentheses for nested ternaries to prevent confusion.

// BAD โ€” hard to read
$result = $a ? $b ? "both" : "only a" : "neither";

// GOOD โ€” use if/elseif for complex logic
if ($a && $b) {
    $result = "both";
} elseif ($a) {
    $result = "only a";
} else {
    $result = "neither";
}

Short Ternary (Elvis Operator)

PHP has a shorthand when you want to use the tested value itself as the "true" result:

<?php
// Normal ternary
$display = $username ? $username : "Anonymous";

// Short ternary (Elvis operator) โ€” same result
$display = $username ?: "Anonymous";

// If $username is truthy, use it; otherwise use "Anonymous"

The ?: is called the "Elvis operator" because if you tilt your head, the characters look like Elvis's hair. Really.

The Null Coalescing Operator

The null coalescing operator (??) was introduced in PHP 7 and quickly became one of the most-loved features. It provides a default value when something is null or undefined.

Basic Syntax

$result = $value ?? $default;

Translation: "Use $value if it exists and isn't null; otherwise, use $default."

<?php
// Before PHP 7 โ€” verbose
$name = isset($_GET['name']) ? $_GET['name'] : "Guest";

// PHP 7+ โ€” clean and concise
$name = $_GET['name'] ?? "Guest";

// They do the same thing, but ?? is much cleaner

Chaining

You can chain multiple ?? operators โ€” PHP uses the first non-null value it finds:

<?php
// Try multiple sources, use the first non-null value
$color = $_GET['color'] ?? $_SESSION['color'] ?? $defaultColor ?? "blue";

// PHP checks each from left to right:
// 1. Is $_GET['color'] set and not null? If yes, use it.
// 2. Is $_SESSION['color'] set and not null? If yes, use it.
// 3. Is $defaultColor set and not null? If yes, use it.
// 4. Fall back to "blue"

Null Coalescing Assignment (??=)

<?php
// Only assign if the variable is null or undefined
$settings['theme'] ??= "light";

// Equivalent to:
if (!isset($settings['theme'])) {
    $settings['theme'] = "light";
}

// Useful for setting defaults:
$config['timeout'] ??= 30;
$config['retries'] ??= 3;
$config['debug'] ??= false;

?? vs. ?:

These look similar but behave differently:

Operator Returns default when value is... Example
?? null or undefined only 0 ?? "default" โ†’ 0
?: Any falsy value (0, "", false, null, etc.) 0 ?: "default" โ†’ "default"
<?php
$count = 0;

echo $count ?? "no data";    // 0   โ€” ?? only checks for null
echo $count ?: "no data";    // "no data" โ€” ?: treats 0 as falsy

// ?? is usually what you want for form/API data
// ?: is useful when you want to reject all falsy values

Operator Precedence

When an expression has multiple operators, PHP evaluates them in a specific order โ€” just like math class where multiplication happens before addition.

Precedence Table (Highest to Lowest)

Priority Operators Description
1 (highest) ** Exponentiation
2 ++ -- ! (type) Increment, decrement, not, casting
3 * / % Multiplication, division, modulo
4 + - . Addition, subtraction, concatenation
5 < <= > >= Comparison
6 == != === !== <=> Equality
7 && Logical AND
8 || Logical OR
9 ?? Null coalescing
10 ?: Ternary
11 = += -= .= etc. Assignment
12 (lowest) and or xor Logical (word form)

Examples

<?php
// Multiplication before addition (like math)
echo 2 + 3 * 4;      // 14, not 20
echo (2 + 3) * 4;    // 20 โ€” parentheses override precedence

// && before ||
$result = true || false && false;
// Evaluates as: true || (false && false) โ†’ true

// Comparison before logical
$result = 5 > 3 && 10 < 20;
// Evaluates as: (5 > 3) && (10 < 20) โ†’ true && true โ†’ true

โœ… The Golden Rule

When in doubt, use parentheses. They make your intent explicit and prevent bugs. Nobody will complain about "too many parentheses" โ€” they'll complain about code that's hard to understand.

// Ambiguous โ€” relies on knowing precedence
$canEdit = $isAdmin || $isOwner && !$isLocked;

// Clear โ€” intent is explicit
$canEdit = $isAdmin || ($isOwner && !$isLocked);

Hands-On Exercises

๐Ÿ‹๏ธ Exercise 1: Price Calculator

Objective: Practice arithmetic and assignment operators by building a simple price calculator.

Instructions:

  1. Create exercise_04a.php in your exercises folder
  2. Define a base price, quantity, tax rate, and discount percentage
  3. Calculate subtotal, discount amount, tax amount, and final total
  4. Output a formatted receipt

Starter Code:

<?php
$basePrice = 29.99;
$quantity = 3;
$taxRate = 0.0825;    // 8.25%
$discountPercent = 10; // 10% off

// TODO: Calculate these
$subtotal = 0;
$discountAmount = 0;
$afterDiscount = 0;
$taxAmount = 0;
$total = 0;

// TODO: Output a formatted receipt
๐Ÿ’ก Hint

Calculate in order: subtotal = price ร— quantity, discount = subtotal ร— (percent/100), after discount = subtotal - discount, tax = after discount ร— rate, total = after discount + tax. Use number_format($value, 2) to format to 2 decimal places.

โœ… Solution
<?php
$basePrice = 29.99;
$quantity = 3;
$taxRate = 0.0825;
$discountPercent = 10;

$subtotal = $basePrice * $quantity;
$discountAmount = $subtotal * ($discountPercent / 100);
$afterDiscount = $subtotal - $discountAmount;
$taxAmount = $afterDiscount * $taxRate;
$total = $afterDiscount + $taxAmount;

echo "===== RECEIPT =====\n";
echo "Price: $" . number_format($basePrice, 2) . " ร— $quantity\n";
echo "Subtotal:  $" . number_format($subtotal, 2) . "\n";
echo "Discount:  -$" . number_format($discountAmount, 2) . " ($discountPercent%)\n";
echo "After Discount: $" . number_format($afterDiscount, 2) . "\n";
echo "Tax:       +$" . number_format($taxAmount, 2) . " (" . ($taxRate * 100) . "%)\n";
echo "-------------------\n";
echo "TOTAL:     $" . number_format($total, 2) . "\n";

๐Ÿ‹๏ธ Exercise 2: Operator Challenge

Objective: Predict the output of each expression, then verify with var_dump().

<?php
// Predict each result before running!

// 1. Arithmetic precedence
$a = 2 + 3 * 4 - 1;

// 2. String vs arithmetic
$b = "10" + "20 cats";

// 3. Null coalescing
$c = null ?? 0 ?? "default";

// 4. Elvis vs null coalescing
$d = "" ?: "empty";
$e = "" ?? "empty";

// 5. Combined comparison
$f = (10 > 5) && (3 <= 3) || false;

// 6. Spaceship
$g = 5 <=> 5;

// 7. Concatenation with types
$h = "Score: " . 95 . "%";

// 8. Assignment returns a value
$i = $j = $k = 42;
โœ… Answers
$a = 2 + 3 * 4 - 1;        // int(13) โ€” 2 + 12 - 1
$b = "10" + "20 cats";      // int(30) โ€” "10" โ†’ 10, "20 cats" โ†’ 20
$c = null ?? 0 ?? "default"; // int(0) โ€” first non-null is 0
$d = "" ?: "empty";          // string("empty") โ€” "" is falsy
$e = "" ?? "empty";          // string("") โ€” "" is not null!
$f = (10 > 5) && (3 <= 3) || false; // bool(true) โ€” true && true = true
$g = 5 <=> 5;              // int(0) โ€” equal
$h = "Score: " . 95 . "%";  // string("Score: 95%") โ€” concatenation
$i = $j = $k = 42;          // All are int(42) โ€” right-to-left assignment

๐ŸŽฏ Quick Quiz

Question 1: What does "5" + "3" evaluate to in PHP?

Question 2: What does $x = 0 ?? "default" assign to $x?

Question 3: What is the result of 10 % 3?

Question 4: What's the key difference between && and and in PHP?

Question 5: What does the ternary expression ($age >= 18) ? "adult" : "minor" return if $age is 18?

Summary

๐ŸŽ‰ Key Takeaways

  • Arithmetic: + - * / % ** โ€” standard math, plus modulo for remainders and exponentiation
  • Assignment: = plus compound forms (+=, -=, .=, etc.) for cleaner code
  • Strings: Use . for concatenation (not +!) and .= to append
  • Comparison: Always prefer === over == to avoid type juggling surprises
  • Logical: &&, ||, ! for combining conditions โ€” use &&/|| not and/or
  • Ternary: condition ? true : false for compact conditionals; don't over-nest
  • Null coalescing: ?? for defaults when null; ??= for assign-if-null
  • Precedence: When in doubt, use parentheses to make intent clear

๐Ÿ“š Additional Resources

๐Ÿš€ What's Next?

You can now calculate, compare, and combine data. In Lesson 5: Control Flow, you'll learn to make decisions with if/elseif/else, switch, and PHP 8's powerful match expression.

๐ŸŽ‰ Congratulations!

You've mastered PHP's operators โ€” the tools that make your data do things. Now let's put them to work with control flow!