Skip to main content

Course Progress

Loading...

Module 2: PHP Comparison Operators

Duration: 30 minutes
Module 2: PHP Operators

Learning Objectives

  • Master PHP operators
  • Understand operator precedence
  • Apply operators in practical scenarios
  • Write efficient expressions

Introduction to PHP Comparison Operators

Welcome to our session on PHP Comparison Operators! These operators are essential tools that allow your programs to make decisions by comparing values. Comparison operators evaluate expressions and return boolean results (true or false), which form the foundation of conditional logic in PHP.

Think of comparison operators as the judges in your code. Just as a judge evaluates evidence and makes a decision, comparison operators evaluate values and determine whether a condition is true or false. Today, we'll explore these operators, understand how they work with different data types, and see how they're used in real-world applications.

Comparison Operators Overview

PHP provides a comprehensive set of comparison operators that allow you to compare values in different ways:

== Equal === Identical != Not Equal <> Not Equal (Alt) !== Not Identical > Greater Than < Less Than >= Greater Than or Equal <= Less Than or Equal <=> Spaceship
Operator Name Example Result
== Equal $x == $y True if $x is equal to $y (after type juggling)
=== Identical $x === $y True if $x is equal to $y, and they are of the same type
!= Not equal $x != $y True if $x is not equal to $y (after type juggling)
<> Not equal $x <> $y True if $x is not equal to $y (after type juggling)
!== Not identical $x !== $y True if $x is not equal to $y, or they are not of the same type
> Greater than $x > $y True if $x is greater than $y
< Less than $x < $y True if $x is less than $y
>= Greater than or equal to $x >= $y True if $x is greater than or equal to $y
<= Less than or equal to $x <= $y True if $x is less than or equal to $y
<=> Spaceship $x <=> $y Returns -1, 0, or 1 when $x is less than, equal to, or greater than $y

Now, let's explore each of these operators in detail with examples and real-world applications.

Equality Operators

Let's start by examining the operators that check for equality or inequality between values.

Equal (==) Operator

The equal operator (==) checks if two values are equal, after type conversion (also known as type juggling). This means PHP will attempt to convert different data types to match before comparison.

Diagram
Yes No >|No| D["Compare values directly"] C > F["Return boolean result"] E $x == $y Convert to matching types Compare values directly Compare converted values Return boolean result Different Types?

Basic Equal Operator Examples

<?php
// Comparing same types
$a = 5;
$b = 5;
$result = ($a == $b);
echo "5 == 5: " . ($result ? 'true' : 'false') . "<br>"; // Outputs: true

// Comparing different types
$c = 5;
$d = "5"; // String
$result = ($c == $d);
echo "5 == \"5\": " . ($result ? 'true' : 'false') . "<br>"; // Outputs: true

// Boolean comparison
$e = true;
$f = 1;
$result = ($e == $f);
echo "true == 1: " . ($result ? 'true' : 'false') . "<br>"; // Outputs: true

// Comparing strings
$g = "hello";
$h = "hello";
$result = ($g == $h);
echo "\"hello\" == \"hello\": " . ($result ? 'true' : 'false') . "<br>"; // Outputs: true

// Null and zero comparison
$i = null;
$j = 0;
$result = ($i == $j);
echo "null == 0: " . ($result ? 'true' : 'false') . "<br>"; // Outputs: true
?>

Analogy: The equal operator (==) is like comparing two dishes based only on their taste, regardless of their ingredients. If they taste the same to you, you consider them equal, even if one is made with sugar and the other with honey.

Identical (===) Operator

The identical operator (===) is stricter than the equal operator. It returns true only if both values are equal AND they are of the same type. No type conversion is performed.

Diagram
No Yes Yes No $x === $y Return false Return true Return false Same Type? Same Value?

Basic Identical Operator Examples

<?php
// Comparing same types
$a = 5;
$b = 5;
$result = ($a === $b);
echo "5 === 5: " . ($result ? 'true' : 'false') . "<br>"; // Outputs: true

// Comparing different types
$c = 5;
$d = "5"; // String
$result = ($c === $d);
echo "5 === \"5\": " . ($result ? 'true' : 'false') . "<br>"; // Outputs: false

// Boolean comparison
$e = true;
$f = 1;
$result = ($e === $f);
echo "true === 1: " . ($result ? 'true' : 'false') . "<br>"; // Outputs: false

// Null and zero comparison
$i = null;
$j = 0;
$result = ($i === $j);
echo "null === 0: " . ($result ? 'true' : 'false') . "<br>"; // Outputs: false
?>

Analogy: The identical operator (===) is like comparing two dishes based on both taste AND ingredients. They must be prepared with exactly the same ingredients in the same way to be considered identical.

Not Equal (!=, <>) Operators

The not equal operators (!= and <>) check if two values are not equal, after type conversion. These are the opposite of the == operator.

Basic Not Equal Operator Examples

<?php
// Comparing same types
$a = 5;
$b = 10;
$result = ($a != $b);
echo "5 != 10: " . ($result ? 'true' : 'false') . "<br>"; // Outputs: true

// Alternative syntax
$result = ($a <> $b);
echo "5 <> 10: " . ($result ? 'true' : 'false') . "<br>"; // Outputs: true

// Comparing different types
$c = 5;
$d = "5"; // String
$result = ($c != $d);
echo "5 != \"5\": " . ($result ? 'true' : 'false') . "<br>"; // Outputs: false (they are equal after type juggling)

// String comparison
$e = "hello";
$f = "world";
$result = ($e != $f);
echo "\"hello\" != \"world\": " . ($result ? 'true' : 'false') . "<br>"; // Outputs: true
?>

Analogy: The not equal operators (!= and <>) are like a taste tester who cares only about whether dishes taste different from each other, regardless of their ingredients.

Not Identical (!==) Operator

The not identical operator (!==) is the opposite of the identical operator. It returns true if the values are not equal OR they are not of the same type.

Basic Not Identical Operator Examples

<?php
// Comparing same types with different values
$a = 5;
$b = 10;
$result = ($a !== $b);
echo "5 !== 10: " . ($result ? 'true' : 'false') . "<br>"; // Outputs: true

// Comparing different types
$c = 5;
$d = "5"; // String
$result = ($c !== $d);
echo "5 !== \"5\": " . ($result ? 'true' : 'false') . "<br>"; // Outputs: true

// Same value, same type
$e = "hello";
$f = "hello";
$result = ($e !== $f);
echo "\"hello\" !== \"hello\": " . ($result ? 'true' : 'false') . "<br>"; // Outputs: false
?>

Analogy: The not identical operator (!==) is like a chef who considers dishes different if they either taste different OR use different ingredients, even if the taste is similar.

Real-World Application: Form Validation

Equality and identity operators are commonly used in form validation to check user inputs:

<?php
// Form validation using comparison operators
function validate_login($username, $password) {
    // Simulated user data from database
    $stored_user = [
        'username' => 'john_doe',
        'password' => 'secret123',
        'account_type' => 'standard',
        'is_active' => true
    ];
    
    $errors = [];
    
    // Check if username matches (case-sensitive)
    if ($username !== $stored_user['username']) {
        $errors[] = "Username does not match. Usernames are case-sensitive.";
    }
    
    // Check if password matches (case-sensitive)
    if ($password !== $stored_user['password']) {
        $errors[] = "Password is incorrect.";
    }
    
    // Check if account is active
    if ($stored_user['is_active'] !== true) {
        $errors[] = "Account is not active.";
    }
    
    return [
        'success' => empty($errors),
        'errors' => $errors
    ];
}

// Test the validation
$result = validate_login('john_doe', 'secret123');
echo "<h4>Login Validation</h4>";
echo "Success: " . ($result['success'] ? 'Yes' : 'No') . "<br>";

if (!$result['success']) {
    echo "Errors:<br>";
    foreach ($result['errors'] as $error) {
        echo "- $error<br>";
    }
}

// Test with incorrect credentials
$result2 = validate_login('john_doe', 'Secret123');
echo "<br>With incorrect password:<br>";
echo "Success: " . ($result2['success'] ? 'Yes' : 'No') . "<br>";

if (!$result2['success']) {
    echo "Errors:<br>";
    foreach ($result2['errors'] as $error) {
        echo "- $error<br>";
    }
}
?>

Best Practices: When to Use == vs. ===

Understanding when to use loose equality (==) versus strict equality (===) is crucial for writing reliable PHP code:

Diagram
Yes No Yes No Need to compare values Use === (identical) Use == (equal) Convert types manually, then use === Same data type expected? Type conversion acceptable?
  • Use === (identical) when:
    • You need to ensure both value and type match
    • Working with booleans, null, or strict type comparisons
    • Comparing return values from functions
    • You want to avoid unexpected type juggling
  • Use == (equal) when:
    • You explicitly want type conversion
    • Comparing user input against numeric values
    • You're certain type differences won't cause issues

Recommendation: As a general practice, use === (identical) by default unless you specifically need type conversion. This helps prevent subtle bugs and makes your code more predictable.

Relational Operators

Relational operators compare the relative positions of values and are commonly used for numeric comparisons and sorting.

Greater Than (>) and Less Than (<) Operators

These operators check if one value is greater than or less than another value.

Basic Examples

<?php
// Numeric comparisons
$a = 10;
$b = 5;
echo "$a > $b: " . ($a > $b ? 'true' : 'false') . "<br>"; // Outputs: true
echo "$a < $b: " . ($a < $b ? 'true' : 'false') . "<br>"; // Outputs: false

// String comparisons (based on lexicographical/dictionary order)
$name1 = "Alice";
$name2 = "Bob";
echo "\"$name1\" < \"$name2\": " . ($name1 < $name2 ? 'true' : 'false') . "<br>"; // Outputs: true

// Case sensitivity in string comparisons
$str1 = "apple";
$str2 = "Apple";
echo "\"$str1\" > \"$str2\": " . ($str1 > $str2 ? 'true' : 'false') . "<br>"; // Outputs: true (lowercase letters have higher ASCII values)

// Type juggling in comparisons
$num = 5;
$str = "3";
echo "$num > \"$str\": " . ($num > $str ? 'true' : 'false') . "<br>"; // Outputs: true (string "3" is converted to number 3)
?>

Analogy: Relational operators are like comparing positions on a number line or words in a dictionary. Greater than checks if a value is to the right of another on the number line, while less than checks if it's to the left.

Greater Than or Equal (>=) and Less Than or Equal (<=) Operators

These operators check if one value is greater than/less than or equal to another value.

Basic Examples

<?php
// Numeric comparisons
$a = 10;
$b = 10;
$c = 5;

echo "$a >= $b: " . ($a >= $b ? 'true' : 'false') . "<br>"; // Outputs: true (equal)
echo "$a >= $c: " . ($a >= $c ? 'true' : 'false') . "<br>"; // Outputs: true (greater)
echo "$c <= $a: " . ($c <= $a ? 'true' : 'false') . "<br>"; // Outputs: true (less)
echo "$b <= $a: " . ($b <= $a ? 'true' : 'false') . "<br>"; // Outputs: true (equal)

// String comparisons
$name1 = "Alice";
$name2 = "Alice";
$name3 = "Bob";

echo "\"$name1\" <= \"$name2\": " . ($name1 <= $name2 ? 'true' : 'false') . "<br>"; // Outputs: true (equal)
echo "\"$name1\" <= \"$name3\": " . ($name1 <= $name3 ? 'true' : 'false') . "<br>"; // Outputs: true (less)
?>

Analogy: These operators are like "inclusive" comparisons on a number line. Greater than or equal checks if a value is to the right of or at the same position as another, while less than or equal checks if it's to the left of or at the same position.

Real-World Application: Grade Calculator

Relational operators are perfect for creating tiered systems like grade calculators:

<?php
function calculate_grade($score) {
    // Validate input first
    if ($score < 0 || $score > 100) {
        return "Invalid score. Please enter a value between 0 and 100.";
    }
    
    // Determine grade using relational operators
    if ($score >= 90) {
        $grade = "A";
    } elseif ($score >= 80) {
        $grade = "B";
    } elseif ($score >= 70) {
        $grade = "C";
    } elseif ($score >= 60) {
        $grade = "D";
    } else {
        $grade = "F";
    }
    
    return $grade;
}

// Test the grade calculator
echo "<h4>Grade Calculator</h4>";
$test_scores = [95, 88, 72, 64, 45, 100, 0, -5, 105];

echo "<table border='1'>";
echo "<tr><th>Score</th><th>Grade</th></tr>";

foreach ($test_scores as $score) {
    $grade = calculate_grade($score);
    echo "<tr>";
    echo "<td>$score</td>";
    echo "<td>$grade</td>";
    echo "</tr>";
}

echo "</table>";
?>

Real-World Application: Age Verification

Relational operators are essential for validating age requirements:

<?php
function verify_age($birth_year, $current_year = null) {
    // If current year is not provided, use the current year
    if ($current_year === null) {
        $current_year = date('Y'); // Gets the current year
    }
    
    // Calculate age
    $age = $current_year - $birth_year;
    
    // Verify age for different services
    $results = [
        'age' => $age,
        'can_vote' => $age >= 18,
        'can_drink' => $age >= 21,
        'senior_discount' => $age >= 65,
        'child_price' => $age <= 12,
        'teenager' => $age >= 13 && $age <= 19
    ];
    
    return $results;
}

// Example usage
echo "<h4>Age Verification System</h4>";

$birth_years = [2010, 2000, 1990, 1955];

foreach ($birth_years as $birth_year) {
    $results = verify_age($birth_year, 2025);
    
    echo "<div class='person'>";
    echo "<h5>Person born in $birth_year (Age: {$results['age']})</h5>";
    echo "<ul>";
    echo "<li>Can vote: " . ($results['can_vote'] ? 'Yes' : 'No') . "</li>";
    echo "<li>Can purchase alcohol: " . ($results['can_drink'] ? 'Yes' : 'No') . "</li>";
    echo "<li>Eligible for senior discount: " . ($results['senior_discount'] ? 'Yes' : 'No') . "</li>";
    echo "<li>Eligible for child pricing: " . ($results['child_price'] ? 'Yes' : 'No') . "</li>";
    echo "<li>Is a teenager: " . ($results['teenager'] ? 'Yes' : 'No') . "</li>";
    echo "</ul>";
    echo "</div>";
}
?>

Spaceship Operator (<=>)

The spaceship operator (<=>) is a three-way comparison operator introduced in PHP 7. It returns:

  • -1 if the left operand is less than the right operand
  • 0 if the operands are equal
  • 1 if the left operand is greater than the right operand
Diagram
$a $b Return -1 Return 0 Return 1 $a |Yes| C["Return -1"] B -->|No| D{"$a == $b?

Basic Spaceship Operator Examples

<?php
// Numeric comparisons
echo "5 <=> 10: " . (5 <=> 10) . "<br>"; // Outputs: -1 (5 is less than 10)
echo "10 <=> 10: " . (10 <=> 10) . "<br>"; // Outputs: 0 (equal)
echo "10 <=> 5: " . (10 <=> 5) . "<br>"; // Outputs: 1 (10 is greater than 5)

// String comparisons
echo "\"apple\" <=> \"banana\": " . ("apple" <=> "banana") . "<br>"; // Outputs: -1
echo "\"banana\" <=> \"banana\": " . ("banana" <=> "banana") . "<br>"; // Outputs: 0
echo "\"cherry\" <=> \"banana\": " . ("cherry" <=> "banana") . "<br>"; // Outputs: 1

// Array comparisons
$arr1 = [1, 2, 3];
$arr2 = [1, 2, 4];
echo "[1, 2, 3] <=> [1, 2, 4]: " . ($arr1 <=> $arr2) . "<br>"; // Outputs: -1
?>

Real-World Application: Custom Sorting

The spaceship operator is particularly useful for custom sorting functions:

<?php
// Product class for demonstration
class Product {
    public $name;
    public $price;
    public $stock;
    
    public function __construct($name, $price, $stock) {
        $this->name = $name;
        $this->price = $price;
        $this->stock = $stock;
    }
}

// Create an array of products
$products = [
    new Product("Laptop", 899.99, 12),
    new Product("Smartphone", 699.99, 25),
    new Product("Tablet", 349.99, 8),
    new Product("Headphones", 149.99, 32),
    new Product("Monitor", 249.99, 15)
];

echo "<h4>Product Sorting with Spaceship Operator</h4>";

// Original products
echo "<h5>Original Product List</h5>";
display_products($products);

// Sort by price (low to high)
usort($products, function($a, $b) {
    return $a->price <=> $b->price;
});

echo "<h5>Sorted by Price (Low to High)</h5>";
display_products($products);

// Sort by stock (high to low)
usort($products, function($a, $b) {
    return $b->stock <=> $a->stock; // Note the reversed order
});

echo "<h5>Sorted by Stock (High to Low)</h5>";
display_products($products);

// Multi-level sort (first by stock availability, then by price)
usort($products, function($a, $b) {
    // First compare if item is in stock (stock > 0)
    $stock_comparison = ($b->stock > 0) <=> ($a->stock > 0);
    
    if ($stock_comparison !== 0) {
        return $stock_comparison;
    }
    
    // If both have same stock status, compare by price
    return $a->price <=> $b->price;
});

echo "<h5>Sorted by Availability, then Price</h5>";
display_products($products);

// Function to display products in a table
function display_products($products) {
    echo "<table border='1'>";
    echo "<tr><th>Name</th><th>Price</th><th>Stock</th></tr>";
    
    foreach ($products as $product) {
        echo "<tr>";
        echo "<td>{$product->name}</td>";
        echo "<td>\${$product->price}</td>";
        echo "<td>{$product->stock}</td>";
        echo "</tr>";
    }
    
    echo "</table>";
}
?>

Analogy: The spaceship operator is like a scale that not only tells you which item is heavier but also indicates equality. It shows whether the left side is lower (-1), balanced (0), or higher (1) than the right side.

String Comparison Details

When comparing strings in PHP, it's important to understand how the comparison works and the role of case sensitivity.

Case Sensitivity in String Comparisons

By default, string comparisons in PHP are case-sensitive. This means 'A' is not equal to 'a'.

Case Sensitivity Examples

<?php
// Case-sensitive comparisons
$str1 = "Hello";
$str2 = "hello";

echo "'$str1' == '$str2': " . ($str1 == $str2 ? 'true' : 'false') . "<br>"; // Outputs: false
echo "'$str1' === '$str2': " . ($str1 === $str2 ? 'true' : 'false') . "<br>"; // Outputs: false

// ASCII values of characters
echo "ASCII value of 'H': " . ord('H') . "<br>"; // Outputs: 72
echo "ASCII value of 'h': " . ord('h') . "<br>"; // Outputs: 104

// Comparing uppercase and lowercase
echo "'A' < 'a': " . ('A' < 'a' ? 'true' : 'false') . "<br>"; // Outputs: true (ASCII 65 < 97)
?>

Case-Insensitive Comparison

For case-insensitive comparisons, you can use the strcasecmp() function or convert strings to the same case before comparing.

<?php
// Case-insensitive comparison using functions
$str1 = "Hello";
$str2 = "hello";

// Using strcasecmp() (returns 0 if strings are equal ignoring case)
$result = strcasecmp($str1, $str2);
echo "strcasecmp('$str1', '$str2'): " . $result . "<br>"; // Outputs: 0 (equal)

// Converting to same case before comparison
$str1_lower = strtolower($str1);
$str2_lower = strtolower($str2);
echo "strtolower('$str1') == strtolower('$str2'): " . ($str1_lower == $str2_lower ? 'true' : 'false') . "<br>"; // Outputs: true

// Real-world example: case-insensitive search
function contains_text($haystack, $needle, $case_sensitive = false) {
    if ($case_sensitive) {
        return strpos($haystack, $needle) !== false;
    } else {
        return stripos($haystack, $needle) !== false;
    }
}

$text = "The quick brown fox jumps over the lazy dog";
$search1 = "FOX";
$search2 = "cat";

echo "Case-insensitive search for '$search1': " . 
     (contains_text($text, $search1, false) ? 'Found' : 'Not found') . "<br>"; // Outputs: Found
     
echo "Case-sensitive search for '$search1': " . 
     (contains_text($text, $search1, true) ? 'Found' : 'Not found') . "<br>"; // Outputs: Not found
     
echo "Search for '$search2': " . 
     (contains_text($text, $search2, false) ? 'Found' : 'Not found') . "<br>"; // Outputs: Not found
?>

Natural Order Comparison

For comparing strings in a more "human-friendly" way, especially strings containing numbers, PHP provides the strnatcmp() and strnatcasecmp() functions.

Natural Order Comparison Examples

<?php
// Standard string comparison
$files = ["file1.txt", "file10.txt", "file2.txt", "file20.txt"];
sort($files);
echo "Standard sort:<br>";
echo implode("<br>", $files) . "<br><br>";
// Outputs: file1.txt, file10.txt, file2.txt, file20.txt

// Natural order comparison
natsort($files);
echo "Natural sort:<br>";
echo implode("<br>", $files);
// Outputs: file1.txt, file2.txt, file10.txt, file20.txt

// Real-world example: sorting product versions
$versions = ["v1.0.9", "v1.10.0", "v1.2.1", "v2.0.0"];
echo "<br><br>Product Versions:<br>";
echo "Original: " . implode(", ", $versions) . "<br>";

// Standard sort
$sorted = $versions;
sort($sorted);
echo "Standard sort: " . implode(", ", $sorted) . "<br>";
// May not give expected results

// Natural sort
$nat_sorted = $versions;
natsort($nat_sorted);
echo "Natural sort: " . implode(", ", $nat_sorted);
// Sorts in version order
?>

Type Juggling in Comparisons

PHP's type juggling (automatic type conversion) can sometimes lead to unexpected results in comparisons. Understanding these behaviors is crucial for writing reliable code.

Diagram
Yes No Yes No Yes No >|No| H{"Both are String/Object/Resource/NULL?"} H $a == $b Compare directly Convert both to Boolean Try to convert non-numeric to number Apply specific conversion rules Same Type? Either is Boolean? Either is Number? Both are String/Object/Resource/NULL?

Common Type Juggling Results

Expression Result Explanation
"42" == 42 true String "42" is converted to integer 42
0 == "0" true String "0" is converted to integer 0
0 == "" true Empty string is converted to 0
0 == false true Both are treated as "falsey" values
null == false true Both are treated as "falsey" values
"0" == false true "0" is converted to integer 0, which is falsey
"abc" == 0 true Non-numeric string converts to 0
[] == false true Empty array is treated as falsey

Type Juggling Examples

<?php
// String to number comparisons
echo "\"42\" == 42: " . ("42" == 42 ? 'true' : 'false') . "<br>"; // true
echo "\"42\" === 42: " . ("42" === 42 ? 'true' : 'false') . "<br>"; // false

// Empty values
echo "0 == \"\": " . (0 == "" ? 'true' : 'false') . "<br>"; // true
echo "0 === \"\": " . (0 === "" ? 'true' : 'false') . "<br>"; // false

// Boolean comparisons
echo "1 == true: " . (1 == true ? 'true' : 'false') . "<br>"; // true
echo "1 === true: " . (1 === true ? 'true' : 'false') . "<br>"; // false
echo "0 == false: " . (0 == false ? 'true' : 'false') . "<br>"; // true
echo "0 === false: " . (0 === false ? 'true' : 'false') . "<br>"; // false

// Null comparisons
echo "null == 0: " . (null == 0 ? 'true' : 'false') . "<br>"; // true
echo "null === 0: " . (null === 0 ? 'true' : 'false') . "<br>"; // false
echo "null == false: " . (null == false ? 'true' : 'false') . "<br>"; // true
echo "null === false: " . (null === false ? 'true' : 'false') . "<br>"; // false

// String to number conversion with non-numeric strings
echo "\"abc\" == 0: " . ("abc" == 0 ? 'true' : 'false') . "<br>"; // true (non-numeric string converts to 0)
echo "\"abc\" === 0: " . ("abc" === 0 ? 'true' : 'false') . "<br>"; // false
?>

Common Pitfalls and How to Avoid Them

<?php
// Pitfall 1: Unintended equality with empty string
function get_user_input() {
    // Simulate user submitting an empty string
    return "";
}

$user_input = get_user_input();
$valid_value = 0;

// WRONG: This will evaluate to true for empty input!
if ($user_input == $valid_value) {
    echo "Pitfall 1: Input accepted (WRONG)<br>";
}

// CORRECT: Use strict comparison
if ($user_input === $valid_value) {
    echo "Input accepted<br>";
} else {
    echo "Pitfall 1 avoided: Empty input rejected (CORRECT)<br>";
}

// Pitfall 2: String comparison with numbers
$value = "42abc"; // Non-numeric part gets ignored in numeric context

// WRONG: Will evaluate to true!
if ($value == 42) {
    echo "Pitfall 2: Value matched (WRONG)<br>";
}

// CORRECT: Validate input first
if (is_numeric($value) && (int)$value === 42) {
    echo "Value matched<br>";
} else {
    echo "Pitfall 2 avoided: Invalid input rejected (CORRECT)<br>";
}

// Pitfall 3: Null equality issues
$user_id = null; // User is not logged in

// WRONG: Will accept user_id = 0, which is a valid ID!
if ($user_id == false) {
    echo "Pitfall 3: User not logged in (may be WRONG)<br>";
}

// CORRECT: Explicitly check for null
if ($user_id === null) {
    echo "Pitfall 3 avoided: User confirmed not logged in (CORRECT)<br>";
}
?>

Complex Comparison Expressions

In real-world scenarios, you'll often need to combine multiple comparison operators with logical operators (AND, OR, NOT) to create complex conditions.

Combining Comparison Operators

<?php
// Checking a value is within a range (between 1 and 100)
$value = 42;
$in_range = ($value >= 1 && $value <= 100);
echo "Is $value between 1 and 100? " . ($in_range ? 'Yes' : 'No') . "<br>";

// Checking multiple conditions with OR
$status = "active";
$role = "admin";
$has_access = ($status === "active" && ($role === "admin" || $role === "manager"));
echo "Has access? " . ($has_access ? 'Yes' : 'No') . "<br>";

// Checking a value matches one of several options
$fruit = "apple";
$is_valid_fruit = ($fruit === "apple" || $fruit === "orange" || $fruit === "banana");
echo "Is $fruit a valid option? " . ($is_valid_fruit ? 'Yes' : 'No') . "<br>";

// Alternative using in_array()
$valid_fruits = ["apple", "orange", "banana"];
$is_valid = in_array($fruit, $valid_fruits, true); // true enables strict comparison
echo "Is $fruit a valid option? " . ($is_valid ? 'Yes' : 'No') . "<br>";
?>

Real-World Application: Product Filtering System

Complex comparisons are essential for filtering systems:

<?php
// Product filtering system
function filter_products($products, $filters) {
    $filtered_products = [];
    
    foreach ($products as $product) {
        $matches_all_criteria = true;
        
        // Check price range
        if (isset($filters['min_price']) && $product['price'] < $filters['min_price']) {
            $matches_all_criteria = false;
        }
        
        if (isset($filters['max_price']) && $product['price'] > $filters['max_price']) {
            $matches_all_criteria = false;
        }
        
        // Check category
        if (isset($filters['category']) && $product['category'] !== $filters['category']) {
            $matches_all_criteria = false;
        }
        
        // Check availability
        if (isset($filters['in_stock']) && $filters['in_stock'] && $product['stock'] <= 0) {
            $matches_all_criteria = false;
        }
        
        // Check rating
        if (isset($filters['min_rating']) && $product['rating'] < $filters['min_rating']) {
            $matches_all_criteria = false;
        }
        
        // If product matches all criteria, add to filtered results
        if ($matches_all_criteria) {
            $filtered_products[] = $product;
        }
    }
    
    return $filtered_products;
}

// Sample product data
$products = [
    [
        'id' => 1,
        'name' => 'Smartphone X',
        'price' => 699.99,
        'category' => 'electronics',
        'stock' => 15,
        'rating' => 4.5
    ],
    [
        'id' => 2,
        'name' => 'Wireless Headphones',
        'price' => 149.99,
        'category' => 'electronics',
        'stock' => 8,
        'rating' => 4.2
    ],
    [
        'id' => 3,
        'name' => 'Running Shoes',
        'price' => 89.99,
        'category' => 'sports',
        'stock' => 0,
        'rating' => 4.7
    ],
    [
        'id' => 4,
        'name' => 'Coffee Maker',
        'price' => 129.99,
        'category' => 'home',
        'stock' => 12,
        'rating' => 3.8
    ],
    [
        'id' => 5,
        'name' => 'Fitness Tracker',
        'price' => 79.99,
        'category' => 'electronics',
        'stock' => 22,
        'rating' => 4.0
    ]
];

// Example filters
$filters = [
    'min_price' => 100,
    'max_price' => 500,
    'category' => 'electronics',
    'in_stock' => true,
    'min_rating' => 4.0
];

$filtered_results = filter_products($products, $filters);

echo "<h4>Product Filtering System</h4>";
echo "<h5>Applied Filters:</h5>";
echo "<ul>";
echo "<li>Price: $" . $filters['min_price'] . " - $" . $filters['max_price'] . "</li>";
echo "<li>Category: " . ucfirst($filters['category']) . "</li>";
echo "<li>In Stock: " . ($filters['in_stock'] ? 'Yes' : 'No') . "</li>";
echo "<li>Minimum Rating: " . $filters['min_rating'] . "</li>";
echo "</ul>";

echo "<h5>Filtered Results:</h5>";

if (empty($filtered_results)) {
    echo "No products match your criteria.";
} else {
    echo "<table border='1'>";
    echo "<tr><th>ID</th><th>Name</th><th>Price</th><th>Category</th><th>Stock</th><th>Rating</th></tr>";
    
    foreach ($filtered_results as $product) {
        echo "<tr>";
        echo "<td>{$product['id']}</td>";
        echo "<td>{$product['name']}</td>";
        echo "<td>${$product['price']}</td>";
        echo "<td>" . ucfirst($product['category']) . "</td>";
        echo "<td>{$product['stock']}</td>";
        echo "<td>{$product['rating']}</td>";
        echo "</tr>";
    }
    
    echo "</table>";
}
?>

Conditional Expressions and Ternary Operator

Comparison operators are often used with conditional expressions, including the ternary operator which provides a shorthand way to write if-else statements.

Ternary Operator Syntax

<?php
// Basic ternary operator syntax
// condition ? value_if_true : value_if_false

$age = 25;
$status = ($age >= 18) ? 'adult' : 'minor';
echo "A person aged $age is considered an $status.<br>";

// Nested ternary operators (use with caution for readability)
$score = 85;
$grade = ($score >= 90) ? 'A' : (($score >= 80) ? 'B' : (($score >= 70) ? 'C' : (($score >= 60) ? 'D' : 'F')));
echo "A score of $score gets a grade of $grade.<br>";

// Shorthand ternary operator (Elvis operator)
// expr1 ?: expr3 (returns expr1 if it evaluates to TRUE, expr3 otherwise)
$username = "";
$display_name = $username ?: "Guest";
echo "Welcome, $display_name!<br>";

// NULL coalescing operator
// expr1 ?? expr2 (returns expr1 if it exists and is not NULL, expr2 otherwise)
$user_color = null;
$default_color = "blue";
$theme_color = $user_color ?? $default_color;
echo "Theme color: $theme_color<br>";
?>

Real-World Application: Dynamic User Interface Elements

Conditionals and comparison operators are essential for creating dynamic UI elements:

<?php
// Simulate user data
$user = [
    'logged_in' => true,
    'username' => 'john_doe',
    'role' => 'editor',
    'theme' => null,
    'notifications' => 3,
    'subscription' => 'premium',
    'last_login' => '2025-03-15'
];

// Generate UI elements based on user data
echo "<h4>Dynamic User Interface Elements</h4>";

// Login/Logout button using ternary
$login_button = $user['logged_in'] 
    ? "<button>Logout ({$user['username']})</button>" 
    : "<button>Login</button>";
echo "Navigation: $login_button<br><br>";

// Welcome message using null coalescing
$display_name = $user['username'] ?? 'Guest';
echo "Welcome, $display_name!<br><br>";

// Notification badge
$notification_badge = $user['notifications'] > 0 
    ? "<span class='badge'>{$user['notifications']}</span>" 
    : "";
echo "Notifications: $notification_badge<br><br>";

// Admin panel access
$admin_access = $user['role'] === 'admin' ? true : false;
echo "Admin Panel: " . ($admin_access ? "Visible" : "Hidden") . "<br><br>";

// Feature access based on subscription
$features_available = $user['subscription'] === 'premium' ? "Full" : "Limited";
echo "Features Available: $features_available<br><br>";

// Theme selection with fallback
$theme = $user['theme'] ?? 'default';
echo "Active Theme: $theme<br><br>";

// User status (active/inactive)
$last_login_timestamp = strtotime($user['last_login']);
$current_timestamp = time();
$days_since_login = floor(($current_timestamp - $last_login_timestamp) / (60 * 60 * 24));
$user_status = $days_since_login < 30 ? 'active' : 'inactive';
echo "Account Status: $user_status (Last login: $days_since_login days ago)";
?>

Best Practices for Using Comparison Operators

  • Use === and !== by default: Strict equality operators prevent unexpected type juggling issues.
  • Be explicit with your intentions: Use parentheses to group complex conditions for clarity and to control operator precedence.
  • Validate user input: Always validate and sanitize user input before comparing it to expected values.
  • Check for null separately: Use === null explicitly when checking for null values rather than == false.
  • Understand string comparison rules: Remember that string comparisons are case-sensitive and based on ASCII/Unicode values.
  • Use appropriate functions: For special comparison needs, use built-in functions like strcasecmp(), in_array(), or version_compare().
  • Avoid nested ternary operators: They can be difficult to read and understand, so use them sparingly.

Best Practices Example

<?php
// GOOD: Clear, explicit comparisons
function validate_user_credentials($username, $password, $remember = false) {
    // Strict comparison for strings
    if ($username === "" || $password === "") {
        return [
            'success' => false,
            'message' => 'Username and password are required'
        ];
    }
    
    // Explicitly check type and value for boolean
    if ($remember !== true && $remember !== false) {
        $remember = false; // Default to false for safety
    }
    
    // Use parentheses for clarity in complex conditions
    if ((strlen($username) < 3 || strlen($username) > 20) || 
        (strlen($password) < 8)) {
        return [
            'success' => false,
            'message' => 'Invalid credentials format'
        ];
    }
    
    // Rest of the validation logic...
    return [
        'success' => true,
        'message' => 'Validation successful',
        'remember' => $remember
    ];
}

// Test the validation
$result = validate_user_credentials("johndoe", "password123", true);
echo "Validation result: " . ($result['success'] ? "Success" : "Failed") . "<br>";
echo "Message: " . $result['message'] . "<br>";
?>

Practice Exercises

Test your understanding of PHP comparison operators with these exercises:

Exercise 1: Comparison Operator Exploration

Create a PHP script that demonstrates the difference between == and === by comparing various values. Include examples with strings, numbers, booleans, and null.

<?php
/*
 * 1. Compare a string "42" with integer 42 using both == and ===
 * 2. Compare boolean true with integer 1 using both == and ===
 * 3. Compare null with integer 0 using both == and ===
 * 4. Compare empty string "" with boolean false using both == and ===
 * 5. Display the results in a table format
 */
?>

Exercise 2: Age Group Classifier

Create a PHP function that classifies a person into different age groups using comparison operators.

<?php
/*
 * 1. Create a function classify_age_group($age) that returns a string representing the age group
 * 2. Use these age ranges:
 *    - "Infant": 0-1 years
 *    - "Toddler": 2-4 years
 *    - "Child": 5-12 years
 *    - "Teenager": 13-19 years
 *    - "Young Adult": 20-35 years
 *    - "Adult": 36-65 years
 *    - "Senior": 66+ years
 * 3. Test your function with various ages and display the results
 */
?>

Exercise 3: Password Strength Checker

Create a PHP function that evaluates password strength using multiple comparison operators and conditional logic.

<?php
/*
 * 1. Create a function check_password_strength($password) that returns "Weak", "Medium", or "Strong"
 * 2. Use these criteria:
 *    - Weak: Less than 8 characters OR only letters/only numbers
 *    - Medium: At least 8 characters AND contains both letters and numbers
 *    - Strong: At least 10 characters AND contains letters, numbers, and special characters
 * 3. Use functions like strlen(), preg_match() to check the password
 * 4. Test your function with various passwords and display the results
 */
?>

Summary

In this session, we've explored PHP's comparison operators and their practical applications:

  • Equality Operators: == (equal), === (identical), != and <> (not equal), !== (not identical)
  • Relational Operators: > (greater than), < (less than), >= (greater than or equal), <= (less than or equal)
  • Spaceship Operator: <=> (combined comparison)

We've also covered important concepts like:

  • Type Juggling: How PHP automatically converts between types during loose comparisons
  • String Comparisons: Case sensitivity, natural order sorting, and how strings are compared
  • Conditional Expressions: Using comparison operators with ternary operators and conditional statements
  • Best Practices: Guidelines for using comparison operators effectively and avoiding common pitfalls

Understanding comparison operators is fundamental to PHP programming as they form the basis of decision-making in your code. Mastering these operators and being aware of their behaviors, especially regarding type juggling, will help you write more reliable and predictable code.

Next Session Preview

In our next session, we'll explore PHP Logical Operators, which allow you to combine multiple conditions and create complex decision structures. We'll learn about operators like AND, OR, XOR, and NOT, which work alongside comparison operators to create sophisticated control flows in your PHP applications.

Additional Resources