Lesson 2.3: Control Structures (if/else, switch)
Control structures are the decision-makers in your code. They examine situations and choose which path your program should take next. Think of them like traffic lights at an intersection—they look at current conditions and direct the flow accordingly. Without control structures, your programs would be like trains on a single track, always doing exactly the same thing in exactly the same order.
Every day, you make countless decisions based on conditions around you. "If it's raining, I'll take an umbrella." "If the store is open, I'll buy groceries." "If I have enough money, I'll get coffee." Control structures let your programs make similar logical decisions automatically, responding intelligently to different situations and user inputs.
The if Statement: Simple Decision Making
The if
statement is your most basic decision-making tool. It checks a condition and runs specific code only when that condition is true. If the condition is false, the code inside the if
block gets skipped entirely.
<?php
$userAge = 16;
$temperature = 75;
$hasUmbrella = true;
// Simple condition checking
if ($userAge >= 18) {
echo "You're old enough to vote!\n";
}
if ($temperature > 80) {
echo "It's hot outside - stay hydrated!\n";
}
if ($hasUmbrella) {
echo "Good thing you brought an umbrella!\n";
}
// Checking user input
$password = "secret123";
if ($password === "secret123") {
echo "Access granted - welcome!\n";
}
// Working with numbers
$accountBalance = 250.50;
if ($accountBalance > 100) {
echo "You have sufficient funds for this purchase.\n";
}
// Boolean conditions
$isLoggedIn = true;
if ($isLoggedIn) {
echo "Welcome back to your dashboard!\n";
}
?>
The key to understanding if
statements is recognizing that they only care about true or false answers. The condition inside the parentheses must evaluate to either true
or false
. If it's true, the code runs. If it's false, PHP skips that entire block and continues with whatever comes next.
The if/else Statement: Two-Path Decisions
Often you need your program to do one thing when a condition is true and something different when it's false. The if/else
statement handles exactly this scenario, ensuring your program always responds appropriately regardless of the condition's outcome.
<?php
$currentHour = 14; // 2 PM in 24-hour format
$isWeekend = false;
$accountBalance = 75.25;
// Time-based decisions
if ($currentHour < 12) {
echo "Good morning!\n";
} else {
echo "Good afternoon!\n";
}
// Weekend vs weekday logic
if ($isWeekend) {
echo "Enjoy your weekend!\n";
} else {
echo "Hope you're having a good workday!\n";
}
// Financial decisions
$itemPrice = 89.99;
if ($accountBalance >= $itemPrice) {
echo "Purchase approved - your new balance is $" . ($accountBalance - $itemPrice) . "\n";
} else {
$shortfall = $itemPrice - $accountBalance;
echo "Insufficient funds - you need $" . number_format($shortfall, 2) . " more\n";
}
// User authentication
$username = "john_doe";
$password = "wrongpassword";
if ($username === "john_doe" && $password === "correctpassword") {
echo "Login successful - redirecting to dashboard\n";
} else {
echo "Invalid username or password - please try again\n";
}
// Age-based access control
$visitorAge = 15;
$parentPresent = true;
if ($visitorAge >= 18) {
echo "Full access granted\n";
} else {
if ($parentPresent) {
echo "Limited access with parental supervision\n";
} else {
echo "Access denied - must be 18 or have parent present\n";
}
}
?>
The else
clause provides a safety net—it catches all cases where the if
condition fails. This ensures your program always has a response, preventing situations where users might be left wondering what happened.
The if/elseif/else Chain: Multiple Conditions
Real applications often need to check several different conditions in sequence. The elseif
construct lets you chain multiple conditions together, creating sophisticated decision trees that can handle complex scenarios.
<?php
$studentGrade = 85;
$weatherCondition = "sunny";
$userRole = "moderator";
// Grade classification system
if ($studentGrade >= 90) {
echo "Excellent work! You earned an A.\n";
} elseif ($studentGrade >= 80) {
echo "Great job! You earned a B.\n";
} elseif ($studentGrade >= 70) {
echo "Good work! You earned a C.\n";
} elseif ($studentGrade >= 60) {
echo "You passed with a D.\n";
} else {
echo "You'll need to retake this course.\n";
}
// Weather-based recommendations
if ($weatherCondition === "sunny") {
echo "Perfect day for outdoor activities!\n";
} elseif ($weatherCondition === "cloudy") {
echo "Good day for a walk in the park.\n";
} elseif ($weatherCondition === "rainy") {
echo "Stay inside with a good book.\n";
} elseif ($weatherCondition === "snowy") {
echo "Time for hot chocolate and a cozy day indoors.\n";
} else {
echo "I'm not sure about today's weather.\n";
}
// User permission system
if ($userRole === "admin") {
echo "Full system access granted\n";
} elseif ($userRole === "moderator") {
echo "Content management access granted\n";
} elseif ($userRole === "user") {
echo "Basic access granted\n";
} elseif ($userRole === "guest") {
echo "Limited read-only access granted\n";
} else {
echo "Unknown user role - access denied\n";
}
// Shipping cost calculator
$orderTotal = 45.00;
$shippingCountry = "US";
$isPremiumMember = false;
if ($isPremiumMember) {
echo "Free shipping for premium members!\n";
} elseif ($orderTotal >= 50) {
echo "Free shipping on orders over $50!\n";
} elseif ($shippingCountry === "US") {
echo "Standard shipping: $5.99\n";
} elseif ($shippingCountry === "Canada") {
echo "International shipping: $12.99\n";
} else {
echo "International shipping: $19.99\n";
}
?>
PHP evaluates elseif
conditions in order from top to bottom. Once it finds a condition that's true, it runs that code block and skips all the remaining conditions. This means the order of your conditions matters—put the most specific or important conditions first.
Nested if Statements: Complex Decision Making
Sometimes you need to check conditions within conditions. Nested if
statements let you create detailed decision structures, though you should be careful not to make them too complicated to understand.
<?php
$age = 16;
$hasLicense = true;
$hasInsurance = false;
$vehicleType = "car";
// Complex driving eligibility check
if ($age >= 16) {
echo "Age requirement met\n";
if ($hasLicense) {
echo "Valid license confirmed\n";
if ($vehicleType === "motorcycle") {
echo "Special motorcycle license required\n";
} else {
if ($hasInsurance) {
echo "All requirements met - you can drive!\n";
} else {
echo "Insurance required before driving\n";
}
}
} else {
echo "Driver's license required\n";
}
} else {
echo "Must be at least 16 years old to drive\n";
}
// Online shopping cart validation
$itemsInCart = 3;
$totalValue = 85.50;
$hasPaymentMethod = true;
$shippingAddress = "123 Main St";
if ($itemsInCart > 0) {
echo "Cart contains $itemsInCart items\n";
if ($totalValue >= 25) {
echo "Minimum order value met\n";
if ($hasPaymentMethod) {
echo "Payment method on file\n";
if (!empty($shippingAddress)) {
echo "Order ready for checkout!\n";
} else {
echo "Please add a shipping address\n";
}
} else {
echo "Please add a payment method\n";
}
} else {
echo "Minimum order is $25.00\n";
}
} else {
echo "Your cart is empty\n";
}
// Game difficulty selection
$playerLevel = 15;
$hasCompletedTutorial = true;
$difficultyPreference = "hard";
if ($hasCompletedTutorial) {
if ($playerLevel >= 20) {
if ($difficultyPreference === "expert") {
echo "Expert mode unlocked - good luck!\n";
} else {
echo "Hard mode available, expert mode unlocked\n";
}
} elseif ($playerLevel >= 10) {
echo "Medium and hard modes available\n";
} else {
echo "Easy and medium modes available\n";
}
} else {
echo "Please complete the tutorial first\n";
}
?>
While nested if
statements are powerful, they can become difficult to read when you have too many levels. If you find yourself nesting more than 2-3 levels deep, consider breaking the logic into separate functions or using different approaches.
The Ternary Operator: Quick Conditional Assignment
The ternary operator provides a shorthand way to write simple if/else
statements. It's perfect for quick decisions where you need to choose between two values based on a condition.
<?php
$userAge = 17;
$temperature = 85;
$accountBalance = 150;
$isLoggedIn = true;
// Basic ternary usage
$ageCategory = ($userAge >= 18) ? "adult" : "minor";
echo "User category: $ageCategory\n";
// Temperature-based clothing suggestion
$clothingSuggestion = ($temperature > 75) ? "wear shorts" : "wear long pants";
echo "Today you should $clothingSuggestion\n";
// Account status display
$accountStatus = ($accountBalance > 0) ? "active" : "overdrawn";
echo "Account status: $accountStatus\n";
// User interface elements
$navigationMenu = $isLoggedIn ? "Dashboard | Profile | Logout" : "Login | Register";
echo "Navigation: $navigationMenu\n";
// Pricing decisions
$membershipType = "premium";
$moviePrice = ($membershipType === "premium") ? 0 : 12.99;
echo "Movie rental cost: $" . number_format($moviePrice, 2) . "\n";
// Form validation messages
$emailAddress = "[email protected]";
$emailValid = filter_var($emailAddress, FILTER_VALIDATE_EMAIL);
$emailMessage = $emailValid ? "Email address is valid" : "Please enter a valid email";
echo "$emailMessage\n";
// Dynamic CSS classes (useful for web development)
$hasErrors = false;
$buttonClass = $hasErrors ? "button-error" : "button-success";
echo "Button CSS class: $buttonClass\n";
// Chaining ternary operators (use sparingly - can become confusing)
$score = 85;
$gradeLevel = ($score >= 90) ? "A" : (($score >= 80) ? "B" : (($score >= 70) ? "C" : "F"));
echo "Grade: $gradeLevel\n";
// Better approach for complex decisions - use regular if/elseif
if ($score >= 90) {
$betterGrade = "A";
} elseif ($score >= 80) {
$betterGrade = "B";
} elseif ($score >= 70) {
$betterGrade = "C";
} else {
$betterGrade = "F";
}
echo "Better grade calculation: $betterGrade\n";
?>
The ternary operator follows the pattern: condition ? value_if_true : value_if_false
. It's excellent for simple choices but becomes hard to read when you chain multiple ternary operators together. For complex decisions, stick with regular if/else
statements.
The switch Statement: Multiple Choice Selection
When you need to compare a single variable against many possible values, the switch
statement is cleaner and more efficient than long if/elseif
chains. It's particularly useful for handling user selections, menu choices, or processing different types of data.
<?php
$dayOfWeek = "Tuesday";
$userAction = "edit";
$fileExtension = "jpg";
// Day of the week handling
switch ($dayOfWeek) {
case "Monday":
echo "Start of the work week - let's get organized!\n";
break;
case "Tuesday":
case "Wednesday":
case "Thursday":
echo "Midweek productivity time!\n";
break;
case "Friday":
echo "TGIF - finish strong!\n";
break;
case "Saturday":
case "Sunday":
echo "Weekend time - relax and recharge!\n";
break;
default:
echo "That doesn't seem like a valid day.\n";
break;
}
// User action processing
switch ($userAction) {
case "view":
echo "Displaying content in read-only mode\n";
break;
case "edit":
echo "Opening editor - you can make changes\n";
break;
case "delete":
echo "Are you sure you want to delete this?\n";
break;
case "share":
echo "Opening sharing options\n";
break;
case "download":
echo "Preparing file for download\n";
break;
default:
echo "Unknown action - please try again\n";
break;
}
// File type processing
switch ($fileExtension) {
case "jpg":
case "jpeg":
case "png":
case "gif":
echo "Image file detected - opening image viewer\n";
break;
case "pdf":
echo "PDF document - opening PDF reader\n";
break;
case "doc":
case "docx":
echo "Word document - opening word processor\n";
break;
case "mp3":
case "wav":
echo "Audio file - opening music player\n";
break;
case "mp4":
case "avi":
echo "Video file - opening video player\n";
break;
default:
echo "Unknown file type - opening with default program\n";
break;
}
?>
Each case
in a switch statement must end with a break
statement, or PHP will continue executing the next case (called "fall-through"). Sometimes this behavior is useful—like when Tuesday, Wednesday, and Thursday all do the same thing—but usually you want each case to be separate.
Advanced switch Usage
Switch statements become particularly powerful when combined with functions, calculations, or more complex logic. Here are some advanced patterns you'll find useful.
<?php
// Calculator operation handler
$operation = "multiply";
$number1 = 15;
$number2 = 4;
switch ($operation) {
case "add":
case "addition":
$result = $number1 + $number2;
echo "$number1 + $number2 = $result\n";
break;
case "subtract":
case "subtraction":
$result = $number1 - $number2;
echo "$number1 - $number2 = $result\n";
break;
case "multiply":
case "multiplication":
$result = $number1 * $number2;
echo "$number1 × $number2 = $result\n";
break;
case "divide":
case "division":
if ($number2 !== 0) {
$result = $number1 / $number2;
echo "$number1 ÷ $number2 = $result\n";
} else {
echo "Error: Cannot divide by zero\n";
}
break;
default:
echo "Unknown operation: $operation\n";
break;
}
// Website theme configuration
$selectedTheme = "dark";
switch ($selectedTheme) {
case "light":
$backgroundColor = "#ffffff";
$textColor = "#000000";
$accentColor = "#007bff";
echo "Light theme activated\n";
break;
case "dark":
$backgroundColor = "#1a1a1a";
$textColor = "#ffffff";
$accentColor = "#66d9ef";
echo "Dark theme activated\n";
break;
case "blue":
$backgroundColor = "#e3f2fd";
$textColor = "#0d47a1";
$accentColor = "#1976d2";
echo "Blue theme activated\n";
break;
case "green":
$backgroundColor = "#e8f5e8";
$textColor = "#2e7d32";
$accentColor = "#4caf50";
echo "Green theme activated\n";
break;
default:
$backgroundColor = "#ffffff";
$textColor = "#000000";
$accentColor = "#007bff";
echo "Unknown theme - using default light theme\n";
break;
}
echo "Theme colors: Background=$backgroundColor, Text=$textColor, Accent=$accentColor\n";
// User role permissions
$userRole = "editor";
switch ($userRole) {
case "admin":
$canDeleteUsers = true;
$canEditContent = true;
$canViewReports = true;
$canManageSettings = true;
echo "Admin access: Full permissions granted\n";
break;
case "editor":
$canDeleteUsers = false;
$canEditContent = true;
$canViewReports = true;
$canManageSettings = false;
echo "Editor access: Content and reporting permissions\n";
break;
case "author":
$canDeleteUsers = false;
$canEditContent = true;
$canViewReports = false;
$canManageSettings = false;
echo "Author access: Content creation permissions\n";
break;
case "viewer":
$canDeleteUsers = false;
$canEditContent = false;
$canViewReports = false;
$canManageSettings = false;
echo "Viewer access: Read-only permissions\n";
break;
default:
$canDeleteUsers = false;
$canEditContent = false;
$canViewReports = false;
$canManageSettings = false;
echo "Unknown role - no permissions granted\n";
break;
}
?>
Notice how switch statements can set multiple variables based on a single condition. This makes them excellent for configuration scenarios where one choice affects several related settings.
Combining Control Structures
Real applications often combine different control structures to handle complex scenarios. Here's how they work together in practical situations.
<?php
// E-commerce order processing system
$customerType = "premium";
$orderTotal = 125.50;
$shippingCountry = "Canada";
$hasPromoCode = true;
$promoCode = "SAVE20";
// Determine shipping cost based on multiple factors
if ($customerType === "premium") {
echo "Premium customer detected\n";
$shippingCost = 0; // Free shipping for premium customers
} else {
switch ($shippingCountry) {
case "US":
$shippingCost = ($orderTotal >= 50) ? 0 : 5.99;
break;
case "Canada":
$shippingCost = ($orderTotal >= 75) ? 0 : 12.99;
break;
case "Mexico":
$shippingCost = ($orderTotal >= 100) ? 0 : 15.99;
break;
default:
$shippingCost = 25.99; // International shipping
break;
}
}
// Apply promotional discount
$discount = 0;
if ($hasPromoCode) {
switch ($promoCode) {
case "SAVE10":
$discount = $orderTotal * 0.10;
echo "10% discount applied\n";
break;
case "SAVE20":
$discount = $orderTotal * 0.20;
echo "20% discount applied\n";
break;
case "FREESHIP":
$shippingCost = 0;
echo "Free shipping promo applied\n";
break;
default:
echo "Invalid promo code\n";
break;
}
}
// Calculate final total
$subtotal = $orderTotal - $discount;
$finalTotal = $subtotal + $shippingCost;
echo "\nOrder Summary:\n";
echo "Original total: $" . number_format($orderTotal, 2) . "\n";
echo "Discount: -$" . number_format($discount, 2) . "\n";
echo "Subtotal: $" . number_format($subtotal, 2) . "\n";
echo "Shipping: $" . number_format($shippingCost, 2) . "\n";
echo "Final total: $" . number_format($finalTotal, 2) . "\n";
// Content access control system
$userAge = 16;
$hasParentPermission = true;
$contentRating = "PG-13";
$userCountry = "US";
echo "\nContent Access Check:\n";
// Age verification
if ($userAge >= 18) {
echo "Adult user - checking content rating\n";
switch ($contentRating) {
case "G":
case "PG":
case "PG-13":
case "R":
echo "Access granted to $contentRating content\n";
break;
case "NC-17":
if ($userAge >= 21) {
echo "Access granted to NC-17 content\n";
} else {
echo "Must be 21+ for NC-17 content\n";
}
break;
default:
echo "Unknown content rating\n";
break;
}
} elseif ($userAge >= 13) {
echo "Teen user - checking parental permission\n";
if ($hasParentPermission) {
switch ($contentRating) {
case "G":
case "PG":
case "PG-13":
echo "Access granted with parental permission\n";
break;
default:
echo "Content too mature - access denied\n";
break;
}
} else {
switch ($contentRating) {
case "G":
case "PG":
echo "Access granted to family-friendly content\n";
break;
default:
echo "Parental permission required\n";
break;
}
}
} else {
echo "Child user - restricted to G-rated content only\n";
if ($contentRating === "G") {
echo "Access granted to G-rated content\n";
} else {
echo "Content not appropriate for children\n";
}
}
?>
Best Practices and Common Mistakes
Understanding common control structure mistakes helps you write more reliable code and debug problems faster when they occur.
<?php
// Mistake 1: Using assignment (=) instead of comparison (==)
$userScore = 100;
// Wrong - this assigns 100 to $userScore, doesn't compare
if ($userScore = 90) {
echo "This will always run because assignment returns the assigned value\n";
}
// Right - this compares $userScore to 90
if ($userScore == 90) {
echo "User scored exactly 90 points\n";
} else {
echo "User scored $userScore points\n";
}
// Mistake 2: Forgetting break statements in switch
$grade = "B";
echo "Without proper breaks:\n";
switch ($grade) {
case "A":
echo "Excellent!\n";
// Missing break - will fall through to next case
case "B":
echo "Good work!\n";
// Missing break - will fall through to next case
case "C":
echo "Satisfactory\n";
break;
default:
echo "Needs improvement\n";
break;
}
echo "\nWith proper breaks:\n";
switch ($grade) {
case "A":
echo "Excellent!\n";
break;
case "B":
echo "Good work!\n";
break;
case "C":
echo "Satisfactory\n";
break;
default:
echo "Needs improvement\n";
break;
}
// Mistake 3: Not handling all possible cases
$dayNumber = 8; // Invalid day number
// Poor approach - doesn't handle invalid input
if ($dayNumber == 1) {
echo "Monday\n";
} elseif ($dayNumber == 2) {
echo "Tuesday\n";
} // ... missing other days and error handling
// Better approach - handles all cases including errors
if ($dayNumber >= 1 && $dayNumber <= 7) {
$days = ["", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
echo $days[$dayNumber] . "\n";
} else {
echo "Invalid day number - must be 1-7\n";
}
// Mistake 4: Overly complex nested conditions
$temperature = 75;
$humidity = 60;
$isRaining = false;
$windSpeed = 5;
// Hard to read and maintain
if ($temperature > 70) {
if ($humidity < 70) {
if (!$isRaining) {
if ($windSpeed < 10) {
echo "Perfect weather for outdoor activities!\n";
} else {
echo "Too windy for some outdoor activities\n";
}
} else {
echo "Too wet for outdoor activities\n";
}
} else {
echo "Too humid for comfortable outdoor activities\n";
}
} else {
echo "Too cold for most outdoor activities\n";
}
// Better approach - clearer logic
$isGoodTemperature = ($temperature > 70);
$isGoodHumidity = ($humidity < 70);
$isGoodWeather = (!$isRaining && $windSpeed < 10);
if ($isGoodTemperature && $isGoodHumidity && $isGoodWeather) {
echo "Perfect weather for outdoor activities!\n";
} elseif (!$isGoodTemperature) {
echo "Too cold for most outdoor activities\n";
} elseif (!$isGoodHumidity) {
echo "Too humid for comfortable outdoor activities\n";
} elseif ($isRaining) {
echo "Too wet for outdoor activities\n";
} else {
echo "Too windy for some outdoor activities\n";
}
?>
Key Takeaways
Control structures give your programs the ability to make intelligent decisions and respond appropriately to different situations. The if
statement handles simple true/false decisions, while if/else
ensures your program always has a response. Use elseif
chains for multiple related conditions, and switch statements when comparing one variable against many possible values.
The ternary operator provides a concise way to choose between two values based on a condition, but don't overuse it for complex decisions. Nested control structures handle sophisticated logic, but keep them readable by limiting nesting depth and using descriptive variable names.
Always consider edge cases and invalid inputs when designing your control structures. Provide appropriate error messages and fallback behaviors to create robust applications that handle unexpected situations gracefully.
Practice combining different control structures to solve real-world problems. The more you work with them, the more naturally you'll recognize which approach fits each situation. Remember that clear, readable code with explicit conditions and helpful comments is always better than clever shortcuts that obscure your program's logic.