Skip to main content

Course Progress

Loading...

PHP Foreach Loops with Arrays - Control Structures

Duration: 45 minutes
Module 2: Loops in PHP

Learning Objectives

  • Master PHP loop structures
  • Choose appropriate loop types
  • Control loop execution flow
  • Optimize loop performance

Introduction to PHP Foreach Loops

Welcome to our session on PHP Foreach Loops with Arrays, a specialized control structure designed specifically for iterating through arrays and objects. The foreach loop is one of the most commonly used loops in PHP and provides an elegant and efficient way to process collections of data.

Think of a foreach loop as a tour guide taking you through every room in a museum – the guide ensures you visit each exhibit exactly once, in a specific order, without having to manually track your progress or worry about how many rooms there are in total.

Diagram
Yes No > C[Execute Code Block with Current Element] C >|Yes| E[Take Next Element] E >|No| F[Exit Loop] F Start Take First Element from Array Execute Code Block with Current Element Take Next Element Exit Loop Continue Program More Elements?

Foreach loops automatically handle all the details of iterating through an array for you, making your code cleaner and less prone to errors compared to using for or while loops with array indices. This is particularly valuable when working with associative arrays, multidimensional arrays, or collections of objects.

Basic Syntax of PHP Foreach Loops

The foreach loop in PHP has two syntax variations:

Syntax 1: Value Only

foreach ($array as $value) {
    // code to be executed for each array element
    // $value contains the current element's value
}

Syntax 2: Key and Value

foreach ($array as $key => $value) {
    // code to be executed for each array element
    // $key contains the current element's key
    // $value contains the current element's value
}
  • $array: The array you want to iterate through
  • $value: A variable that will hold the value of the current array element in each iteration
  • $key: A variable that will hold the key/index of the current array element (optional)

Think of the foreach loop as a conveyor belt in a factory – each item (array element) passes through, and you can examine or modify it as it goes by. You can also check the label (key) attached to each item if needed.

Example: Basic Foreach Loop with Indexed Array

<?php
// Define an indexed array
$fruits = ["Apple", "Banana", "Cherry", "Date", "Elderberry"];

// Iterate through the array with foreach
foreach ($fruits as $fruit) {
    echo "I like eating $fruit<br>";
}
?>

Output:

I like eating Apple
I like eating Banana
I like eating Cherry
I like eating Date
I like eating Elderberry

Example: Foreach Loop with Keys and Values

<?php
// Define an associative array
$fruitColors = [
    "Apple" => "Red",
    "Banana" => "Yellow",
    "Blueberry" => "Blue",
    "Grape" => "Purple",
    "Lime" => "Green"
];

// Iterate through the array with keys and values
foreach ($fruitColors as $fruit => $color) {
    echo "A $fruit is $color<br>";
}
?>

Output:

A Apple is Red
A Banana is Yellow
A Blueberry is Blue
A Grape is Purple
A Lime is Green

In these examples, the foreach loop automatically handles the iteration process, eliminating the need to initialize counters, check conditions, or increment indices as you would with for or while loops.

Foreach vs. Other Loop Types

To understand when to use foreach loops instead of other loop types, let's compare them:

Loop Type When to Use foreach foreach ($array as $value) foreach ($array as $key => $value) • When working with arrays or objects • When you need every element in the collection • When the order of iteration matches the collection order • When you need associative array keys for for ($i = 0; $i < count($array); $i++) • When you need precise control over indices • When you need to skip elements or iterate backwards • When you need to modify the loop variable during iteration • When you know exactly how many iterations you need while / do-while while (condition) do { ... } while (condition); • When the number of iterations is unknown beforehand • When loop continuation depends on a condition • When processing input until a specific condition is met • When you need at least one execution (do-while) Example: Iterate through an associative array Foreach: Simple and readable with direct key access For/While: Requires manual key extraction, more complex and error-prone

Let's compare using different loop types to iterate through the same associative array:

Using foreach (Recommended for arrays)

<?php
$ages = [
    "John" => 25,
    "Mary" => 30,
    "Bob" => 22,
    "Alice" => 28
];

// Using foreach - simple and intuitive
foreach ($ages as $name => $age) {
    echo "$name is $age years old.<br>";
}
?>

Using for with array_keys (More complicated)

<?php
$ages = [
    "John" => 25,
    "Mary" => 30,
    "Bob" => 22,
    "Alice" => 28
];

// Using for loop - requires more setup
$keys = array_keys($ages);
$count = count($keys);

for ($i = 0; $i < $count; $i++) {
    $name = $keys[$i];
    $age = $ages[$name];
    echo "$name is $age years old.<br>";
}
?>

As you can see, the foreach loop is much more concise and readable when working with arrays, especially associative arrays. It's like having an automatic tour guide versus manually navigating with a map – both will get you to all the destinations, but the guide (foreach) makes the journey simpler and less error-prone.

Working with Different Array Types

Indexed Arrays

Indexed arrays have numeric keys, usually starting from 0:

<?php
// Indexed array
$colors = ["Red", "Green", "Blue", "Yellow", "Purple"];

// Iterate with just values
foreach ($colors as $color) {
    echo "Color: $color<br>";
}

echo "<hr>";

// Iterate with indices and values
foreach ($colors as $index => $color) {
    echo "Color at index $index: $color<br>";
}
?>

Output:

Color: Red
Color: Green
Color: Blue
Color: Yellow
Color: Purple
------------------------------
Color at index 0: Red
Color at index 1: Green
Color at index 2: Blue
Color at index 3: Yellow
Color at index 4: Purple

When working with indexed arrays, you might not always need the index. However, including it can be helpful when you need to reference the position of elements.

Associative Arrays

Associative arrays use string keys instead of numeric indices:

<?php
// Associative array
$countryCapitals = [
    "USA" => "Washington D.C.",
    "UK" => "London",
    "France" => "Paris",
    "Germany" => "Berlin",
    "Japan" => "Tokyo"
];

// Iterate with just values
foreach ($countryCapitals as $capital) {
    echo "Capital city: $capital<br>";
}

echo "<hr>";

// Iterate with keys and values
foreach ($countryCapitals as $country => $capital) {
    echo "The capital of $country is $capital<br>";
}
?>

Output:

Capital city: Washington D.C.
Capital city: London
Capital city: Paris
Capital city: Berlin
Capital city: Tokyo
------------------------------
The capital of USA is Washington D.C.
The capital of UK is London
The capital of France is Paris
The capital of Germany is Berlin
The capital of Japan is Tokyo

For associative arrays, using the key => value syntax is often essential, as the keys typically have meaning and are needed for context.

Multidimensional Arrays

Multidimensional arrays contain other arrays as elements:

<?php
// Multidimensional array
$students = [
    [
        "name" => "John Doe",
        "age" => 20,
        "grades" => ["Math" => 90, "English" => 85, "Science" => 92]
    ],
    [
        "name" => "Jane Smith",
        "age" => 22,
        "grades" => ["Math" => 88, "English" => 94, "Science" => 89]
    ],
    [
        "name" => "Bob Johnson",
        "age" => 21,
        "grades" => ["Math" => 85, "English" => 82, "Science" => 88]
    ]
];

// Iterate through the main array
foreach ($students as $student) {
    echo "Student: " . $student["name"] . " (Age: " . $student["age"] . ")<br>";
    echo "Grades: <br>";
    
    // Nested foreach for the grades array
    foreach ($student["grades"] as $subject => $grade) {
        echo "- $subject: $grade<br>";
    }
    
    echo "<hr>";
}
?>

Output:

Student: John Doe (Age: 20)
Grades: 
- Math: 90
- English: 85
- Science: 92
------------------------------
Student: Jane Smith (Age: 22)
Grades: 
- Math: 88
- English: 94
- Science: 89
------------------------------
Student: Bob Johnson (Age: 21)
Grades: 
- Math: 85
- English: 82
- Science: 88
------------------------------

Nested foreach loops are the perfect tool for working with multidimensional arrays. They allow you to navigate through complex data structures with clarity and simplicity. It's like exploring a building with multiple floors and rooms – the outer loop takes you to each floor, and the inner loop takes you to each room on that floor.

Advanced Techniques with Foreach

Modifying Array Elements

By default, foreach works with a copy of the array elements. To modify the original array, use the & reference operator:

<?php
// Original array
$numbers = [1, 2, 3, 4, 5];
echo "Original array: " . implode(", ", $numbers) . "<br>";

// Attempt to modify WITHOUT references - This WON'T work!
foreach ($numbers as $number) {
    $number *= 2; // This modifies the copy, not the original
}
echo "After foreach without references: " . implode(", ", $numbers) . "<br>";

// Modify WITH references - This WILL work!
foreach ($numbers as &$number) {
    $number *= 2; // This modifies the original array
}
echo "After foreach with references: " . implode(", ", $numbers) . "<br>";

// IMPORTANT: Unset the reference after the loop
unset($number);
?>

Output:

Original array: 1, 2, 3, 4, 5
After foreach without references: 1, 2, 3, 4, 5
After foreach with references: 2, 4, 6, 8, 10

Important Safety Tip:

Always unset the reference variable ($number in this example) after the loop. Failure to do so can lead to unexpected behavior if the variable is used later, as it still references the last array element.

Using references in foreach is like having a direct connection to the original items instead of working with copies. It's similar to editing a document directly versus making edits to a photocopy – only the direct edits affect the original.

Using list() with foreach

You can use the list() construct to break apart array elements in a foreach loop:

<?php
// Array of coordinates
$points = [
    [10, 20],
    [30, 40],
    [50, 60],
    [70, 80]
];

// Use list() to break apart each coordinate
foreach ($points as list($x, $y)) {
    echo "Point coordinates: x=$x, y=$y<br>";
}

// Array of records
$records = [
    ['John Doe', 'Developer', 75000],
    ['Jane Smith', 'Designer', 70000],
    ['Bob Johnson', 'Manager', 85000]
];

// Use list() with named keys (PHP 7.1+)
foreach ($records as list($name, $position, $salary)) {
    echo "$name works as a $position and earns $$salary per year.<br>";
}
?>

Output:

Point coordinates: x=10, y=20
Point coordinates: x=30, y=40
Point coordinates: x=50, y=60
Point coordinates: x=70, y=80
John Doe works as a Developer and earns $75000 per year.
Jane Smith works as a Designer and earns $70000 per year.
Bob Johnson works as a Manager and earns $85000 per year.

The list() construct with foreach is particularly useful when working with arrays that represent structured data. It's like unpacking a box of related items – instead of dealing with the entire box, you get each item separately for easier handling.

Creating Dynamic Variable Names

You can use foreach with variable variables to dynamically create variable names:

<?php
// Data from a form or database
$formData = [
    "first_name" => "John",
    "last_name" => "Doe",
    "email" => "john.doe@example.com",
    "age" => 35
];

// Create variables from the array keys
foreach ($formData as $key => $value) {
    // This creates variables like $first_name, $last_name, etc.
    $$key = $value;
}

// Now we can use these variables directly
echo "The user is $first_name $last_name<br>";
echo "Contact: $email<br>";
echo "Age: $age<br>";
?>

Output:

The user is John Doe
Contact: john.doe@example.com
Age: 35

Security Warning:

Be extremely careful when using variable variables with data from external sources like forms or databases. Always validate and sanitize the data to prevent security issues. This technique should generally be avoided in production code unless absolutely necessary and properly secured.

Dynamic variable creation is like having a label maker that automatically creates and attaches labels to objects based on their properties. It's powerful but should be used with caution.

Performance Considerations

Diagram
> C[References] A > E[Array Copying] B > C1[Use references wisely] D Foreach Performance Large Arrays References Nested Loops Array Copying Consider chunking or iterators Use references wisely Optimize inner loops Be aware of memory usage

When using foreach loops, keep these performance considerations in mind:

  • Memory Usage: Foreach creates a copy of each array element by default. For large arrays or objects, this can be memory-intensive.
  • References: Using references (&) can reduce memory usage, but introduces complexity and potential bugs if not properly managed.
  • Nested Loops: Nested foreach loops have O(n²) time complexity, which can become slow for large arrays. Consider optimizing or restructuring if performance is critical.
  • Array Functions: For simple operations, array functions like array_map() or array_filter() might be more efficient than foreach loops.
  • Iterator Objects: For extremely large datasets, consider using iterator objects which can be more memory-efficient than arrays.

Memory Usage Comparison

<?php
// Create a large array for testing
$largeArray = range(1, 100000);

// Memory usage examples
$startMemory = memory_get_usage();

// Example 1: Foreach without reference (creates copies)
foreach ($largeArray as $value) {
    // Do something with $value
    $dummy = $value * 2;
}
$memoryAfterRegular = memory_get_usage();

// Reset for the next test
unset($value, $dummy);
$memoryAfterReset = memory_get_usage();

// Example 2: Foreach with reference (no copies)
foreach ($largeArray as &$value) {
    // Do something with $value
    $value *= 2;
}
$memoryAfterReference = memory_get_usage();

// Don't forget to unset the reference!
unset($value);

// Print results
echo "Memory usage with regular foreach: " . ($memoryAfterRegular - $startMemory) . " bytes<br>";
echo "Memory after reset: " . ($memoryAfterReset - $startMemory) . " bytes<br>";
echo "Memory usage with reference foreach: " . ($memoryAfterReference - $memoryAfterReset) . " bytes<br>";
?>

Using references can significantly reduce memory usage when working with large arrays or objects. However, always remember to unset the reference variable after the loop to prevent unexpected behavior.

Think of it as the difference between making photocopies of every document you process (more memory) versus working with the originals directly (less memory but more responsibility).

Real-World Examples

HTML Table Generation

Foreach loops are perfect for generating HTML content from array data:

<?php
// Array of products
$products = [
    [
        "id" => 101,
        "name" => "Smartphone XYZ",
        "price" => 599.99,
        "stock" => 25
    ],
    [
        "id" => 102,
        "name" => "Laptop Pro",
        "price" => 1299.99,
        "stock" => 10
    ],
    [
        "id" => 103,
        "name" => "Wireless Headphones",
        "price" => 149.99,
        "stock" => 50
    ],
    [
        "id" => 104,
        "name" => "Smart Watch",
        "price" => 249.99,
        "stock" => 15
    ]
];

// Generate an HTML table
echo "<table border='1'>";
echo "<thead>";
echo "<tr>";
echo "<th>ID</th>";
echo "<th>Product Name</th>";
echo "<th>Price</th>";
echo "<th>Stock</th>";
echo "<th>Total Value</th>";
echo "</tr>";
echo "</thead>";
echo "<tbody>";

$totalInventoryValue = 0;

foreach ($products as $product) {
    $totalValue = $product["price"] * $product["stock"];
    $totalInventoryValue += $totalValue;
    
    echo "<tr>";
    echo "<td>" . $product["id"] . "</td>";
    echo "<td>" . $product["name"] . "</td>";
    echo "<td>$" . number_format($product["price"], 2) . "</td>";
    echo "<td>" . $product["stock"] . "</td>";
    echo "<td>$" . number_format($totalValue, 2) . "</td>";
    echo "</tr>";
}

echo "</tbody>";
echo "<tfoot>";
echo "<tr>";
echo "<td colspan='4'><strong>Total Inventory Value</strong></td>";
echo "<td><strong>$" . number_format($totalInventoryValue, 2) . "</strong></td>";
echo "</tr>";
echo "</tfoot>";
echo "</table>";
?>

Output:

ID Product Name Price Stock Total Value
101 Smartphone XYZ $599.99 25 $14,999.75
102 Laptop Pro $1,299.99 10 $12,999.90
103 Wireless Headphones $149.99 50 $7,499.50
104 Smart Watch $249.99 15 $3,749.85
Total Inventory Value $39,249.00

This example shows how foreach can be used to generate HTML tables from array data. It's like having a template that automatically formats and displays data in a structured way.

Data Filtering and Transformation

Foreach loops are excellent for filtering and transforming array data:

<?php
// Array of student records
$students = [
    [
        "id" => 1,
        "name" => "Alice Johnson",
        "grade" => 85,
        "status" => "active"
    ],
    [
        "id" => 2,
        "name" => "Bob Smith",
        "grade" => 72,
        "status" => "inactive"
    ],
    [
        "id" => 3,
        "name" => "Charlie Brown",
        "grade" => 90,
        "status" => "active"
    ],
    [
        "id" => 4,
        "name" => "David Williams",
        "grade" => 68,
        "status" => "active"
    ],
    [
        "id" => 5,
        "name" => "Emily Davis",
        "grade" => 95,
        "status" => "active"
    ]
];

// Filter: Get only active students with grades above 80
$highPerformers = [];
foreach ($students as $student) {
    if ($student["status"] === "active" && $student["grade"] > 80) {
        $highPerformers[] = $student;
    }
}

echo "<h3>High Performing Active Students:</h3>";
echo "<ul>";
foreach ($highPerformers as $student) {
    echo "<li>" . $student["name"] . " - Grade: " . $student["grade"] . "</li>";
}
echo "</ul>";

// Transform: Create a new array with just names and formatted grades
$formattedRecords = [];
foreach ($students as $student) {
    // Add letter grade based on numeric score
    $letterGrade = "F";
    if ($student["grade"] >= 90) $letterGrade = "A";
    else if ($student["grade"] >= 80) $letterGrade = "B";
    else if ($student["grade"] >= 70) $letterGrade = "C";
    else if ($student["grade"] >= 60) $letterGrade = "D";
    
    $formattedRecords[] = [
        "student_name" => $student["name"],
        "numeric_grade" => $student["grade"],
        "letter_grade" => $letterGrade
    ];
}

echo "<h3>Formatted Student Records:</h3>";
echo "<table border='1'>";
echo "<tr><th>Name</th><th>Numeric Grade</th><th>Letter Grade</th></tr>";
foreach ($formattedRecords as $record) {
    echo "<tr>";
    echo "<td>" . $record["student_name"] . "</td>";
    echo "<td>" . $record["numeric_grade"] . "</td>";
    echo "<td>" . $record["letter_grade"] . "</td>";
    echo "</tr>";
}
echo "</table>";
?>

Output:

High Performing Active Students:

  • Alice Johnson - Grade: 85
  • Charlie Brown - Grade: 90
  • Emily Davis - Grade: 95

Formatted Student Records:

Name Numeric Grade Letter Grade
Alice Johnson 85 B
Bob Smith 72 C
Charlie Brown 90 A
David Williams 68 D
Emily Davis 95 A

This example demonstrates how foreach loops can be used to filter and transform array data. The first loop filters students based on criteria, and the second loop transforms the data into a new format. It's like having a data processing pipeline that sorts, filters, and repackages information according to specific requirements.

Building Database Queries

Foreach loops are useful for dynamically building database queries:

<?php
// Search criteria from a form
$searchCriteria = [
    "first_name" => "John",
    "status" => "active",
    "min_age" => 25
    // 'last_name' and other fields are not specified
];

// Ignore empty values
$filteredCriteria = [];
foreach ($searchCriteria as $key => $value) {
    if (!empty($value)) {
        $filteredCriteria[$key] = $value;
    }
}

// Build the WHERE clause
$whereConditions = [];
$params = [];

foreach ($filteredCriteria as $column => $value) {
    // Handle special cases like min_age
    if ($column === "min_age") {
        $whereConditions[] = "age >= ?";
        $params[] = $value;
    }
    // Regular equality condition
    else {
        $whereConditions[] = "$column = ?";
        $params[] = $value;
    }
}

// Create the full query
$whereClause = "";
if (!empty($whereConditions)) {
    $whereClause = "WHERE " . implode(" AND ", $whereConditions);
}

$query = "SELECT * FROM users $whereClause";

// In a real application, you would use prepared statements:
// $stmt = $pdo->prepare($query);
// $stmt->execute($params);

// For demonstration purposes, we'll just show the query and params
echo "Generated Query: $query<br>";
echo "Parameters: " . implode(", ", $params);
?>

Output:

Generated Query: SELECT * FROM users WHERE first_name = ? AND status = ? AND age >= ?
Parameters: John, active, 25

This example shows how foreach can be used to dynamically build a database query based on user input. It's like having a custom query builder that adapts its structure based on available information.

Security Note:

Always use prepared statements with parameter binding when building dynamic queries to prevent SQL injection attacks. The example above shows a safe approach using placeholders.

Best Practices and Pitfalls

Diagram
> C[Handle References Properly] A > E[Array Modifications] B > C1[Unset references after loop] C > D1[Optimize nested loops] D > E1[Be cautious when modifying] E Foreach Best Practices Choose Right Syntax Handle References Properly Consider Performance Array Modifications Value-only for simple iterations Key-value when you need the keys Unset references after loop Document reference usage Optimize nested loops Consider alternative functions Be cautious when modifying Use proper techniques

Best Practices

  • Choose the right syntax: Use the value-only syntax when you don't need the keys, and the key-value syntax when you do.
  • Handle references properly: Always unset reference variables after using them in foreach loops.
  • Consider performance: For large arrays, be mindful of memory usage and consider optimizations like references or chunking.
  • Readability: Foreach loops often result in more readable code than manual index management with for loops.
  • Use early returns or continues: For complex logic, using continue or return early can make code more readable than deep nesting.

Common Pitfalls

Forgotten References

One of the most common errors with foreach loops is not unsetting reference variables:

<?php
// PROBLEMATIC CODE:
$numbers = [1, 2, 3, 4, 5];

// Modify array with references
foreach ($numbers as &$number) {
    $number *= 2;
}
// Oops! Forgot to unset $number

// Later in the code...
foreach ($numbers as $number) {
    echo "$number "; // This might not behave as expected
}
// The last element of $numbers might be unexpectedly modified

// CORRECT CODE:
$numbers = [1, 2, 3, 4, 5];

// Modify array with references
foreach ($numbers as &$number) {
    $number *= 2;
}
unset($number); // Always unset the reference variable

// Now this will behave as expected
foreach ($numbers as $number) {
    echo "$number ";
}
?>

In the problematic code, the variable $number remains a reference to the last element of the array after the first loop. This can cause unexpected behavior in subsequent code, especially if there's another foreach loop that uses the same variable name. Always unset reference variables after using them.

Modifying Arrays While Iterating

Modifying the array structure while iterating over it can lead to unexpected results:

<?php
// PROBLEMATIC CODE:
$fruits = ["Apple", "Banana", "Cherry", "Date"];

foreach ($fruits as $key => $fruit) {
    echo "Processing $fruit...<br>";
    
    // This can cause unexpected behavior
    if ($fruit === "Banana") {
        unset($fruits[$key]); // Removing an element during iteration
    }
    if ($fruit === "Cherry") {
        $fruits[] = "Elderberry"; // Adding an element during iteration
    }
}

echo "Final array: " . implode(", ", $fruits);

// BETTER APPROACH:
$fruits = ["Apple", "Banana", "Cherry", "Date"];
$fruitsToRemove = [];
$fruitsToAdd = [];

// First pass: Identify modifications
foreach ($fruits as $key => $fruit) {
    echo "First pass: $fruit...<br>";
    
    if ($fruit === "Banana") {
        $fruitsToRemove[] = $key;
    }
    if ($fruit === "Cherry") {
        $fruitsToAdd[] = "Elderberry";
    }
}

// Apply modifications after the loop
foreach ($fruitsToRemove as $key) {
    unset($fruits[$key]);
}
foreach ($fruitsToAdd as $fruit) {
    $fruits[] = $fruit;
}

echo "Final array with better approach: " . implode(", ", $fruits);
?>

Modifying the structure of an array (adding or removing elements) while iterating over it can lead to elements being skipped or processed multiple times. It's better to collect the changes you want to make, then apply them after the loop completes.

Assuming Key Order

Don't assume that foreach will iterate through array keys in a specific order:

<?php
// PROBLEMATIC ASSUMPTION:
$user = [
    "id" => 123,
    "first_name" => "John",
    "last_name" => "Doe",
    "age" => 30
];

// Assuming keys will be in a specific order
$counter = 0;
foreach ($user as $value) {
    if ($counter === 0) {
        echo "User ID: $value<br>"; // May not be the ID
    }
    else if ($counter === 1) {
        echo "First Name: $value<br>"; // May not be the first name
    }
    $counter++;
}

// BETTER APPROACH:
// Access keys directly by name
echo "User ID: " . $user["id"] . "<br>";
echo "First Name: " . $user["first_name"] . "<br>";

// Or use the key in the foreach loop
foreach ($user as $key => $value) {
    echo ucfirst(str_replace("_", " ", $key)) . ": $value<br>";
}
?>

While PHP does maintain insertion order for array elements in modern versions, it's bad practice to rely on this behavior. Always use the key => value syntax when the key names are important, or access array elements directly by their keys.

Array Functions as Alternatives

PHP provides several built-in array functions that can sometimes be more concise or efficient than foreach loops:

array_map()

Apply a function to each element of an array:

<?php
// Using foreach
$numbers = [1, 2, 3, 4, 5];
$doubled = [];
foreach ($numbers as $number) {
    $doubled[] = $number * 2;
}
echo "Doubled with foreach: " . implode(", ", $doubled) . "<br>";

// Using array_map
$doubled = array_map(function($number) {
    return $number * 2;
}, $numbers);
echo "Doubled with array_map: " . implode(", ", $doubled) . "<br>";

// With arrow functions (PHP 7.4+)
$doubled = array_map(fn($number) => $number * 2, $numbers);
echo "Doubled with array_map and arrow function: " . implode(", ", $doubled);
?>

Output:

Doubled with foreach: 2, 4, 6, 8, 10
Doubled with array_map: 2, 4, 6, 8, 10
Doubled with array_map and arrow function: 2, 4, 6, 8, 10

array_filter()

Filter elements of an array using a callback function:

<?php
// Using foreach
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
$evens = [];
foreach ($numbers as $number) {
    if ($number % 2 === 0) {
        $evens[] = $number;
    }
}
echo "Even numbers with foreach: " . implode(", ", $evens) . "<br>";

// Using array_filter
$evens = array_filter($numbers, function($number) {
    return $number % 2 === 0;
});
echo "Even numbers with array_filter: " . implode(", ", $evens) . "<br>";

// With arrow functions (PHP 7.4+)
$evens = array_filter($numbers, fn($number) => $number % 2 === 0);
echo "Even numbers with array_filter and arrow function: " . implode(", ", $evens);
?>

Output:

Even numbers with foreach: 2, 4, 6, 8, 10
Even numbers with array_filter: 2, 4, 6, 8, 10
Even numbers with array_filter and arrow function: 2, 4, 6, 8, 10

array_reduce()

Reduce an array to a single value:

<?php
// Using foreach
$numbers = [1, 2, 3, 4, 5];
$sum = 0;
foreach ($numbers as $number) {
    $sum += $number;
}
echo "Sum with foreach: $sum<br>";

// Using array_reduce
$sum = array_reduce($numbers, function($carry, $number) {
    return $carry + $number;
}, 0);
echo "Sum with array_reduce: $sum<br>";

// With arrow functions (PHP 7.4+)
$sum = array_reduce($numbers, fn($carry, $number) => $carry + $number, 0);
echo "Sum with array_reduce and arrow function: $sum<br>";

// More complex example: find maximum value
$max = array_reduce($numbers, function($carry, $number) {
    return ($number > $carry) ? $number : $carry;
}, PHP_INT_MIN);
echo "Maximum value: $max";
?>

Output:

Sum with foreach: 15
Sum with array_reduce: 15
Sum with array_reduce and arrow function: 15
Maximum value: 5

Choosing Between Foreach and Array Functions

When deciding between foreach loops and array functions, consider these factors:

Use foreach when:

  • The operation is complex or involves multiple steps
  • You need to break out of the loop early
  • You need direct access to both keys and values
  • Code readability is more important than conciseness
  • You're working with beginners who might not be familiar with array functions

Use array functions when:

  • The operation is simple and fits one of the built-in functions
  • You prefer functional programming style
  • You need to chain multiple operations together
  • Performance is critical (array functions can sometimes be faster)
  • Conciseness is valued over explicitness

Array functions can make code more concise and sometimes more readable, but foreach loops often provide more flexibility and explicit control flow. Choose the approach that best fits your specific needs and coding style.

Practice Exercises

Exercise 1: Product Catalog

Create a product catalog display system using a multidimensional array and foreach loops:

<?php
// Start with this code template
$products = [
    [
        "id" => 1001,
        "name" => "Smartphone X",
        "category" => "Electronics",
        "price" => 799.99,
        "features" => ["5G", "128GB Storage", "Dual Camera"]
    ],
    [
        "id" => 1002,
        "name" => "Coffee Maker",
        "category" => "Kitchen",
        "price" => 49.99,
        "features" => ["Programmable", "Auto Shut-off", "12-cup"]
    ],
    [
        "id" => 1003,
        "name" => "Running Shoes",
        "category" => "Sports",
        "price" => 89.99,
        "features" => ["Lightweight", "Water Resistant", "Cushioned Sole"]
    ]
];

// Use foreach loops to:
// 1. Generate a product list with all products
// 2. Create a category filter that shows products by category
// 3. Format and display features as bullet points for each product
?>

Hint:

Use nested foreach loops to iterate through the main array and the features array for each product. Use an associative array to group products by category for the filter functionality.

Exercise 2: Form Data Processing

Create a script that simulates processing form data with validation:

<?php
// Start with this code template
$formData = [
    "username" => "john_doe",
    "email" => "john@example",  // intentionally invalid
    "age" => "thirty",  // intentionally invalid
    "password" => "pass123",
    "confirm_password" => "pass456"  // intentionally doesn't match
];

$validationRules = [
    "username" => ["required", "min:4", "max:20"],
    "email" => ["required", "email"],
    "age" => ["required", "numeric", "min:18"],
    "password" => ["required", "min:8"],
    "confirm_password" => ["required", "same:password"]
];

// Use foreach loops to:
// 1. Validate each field according to its rules
// 2. Collect all validation errors
// 3. Display the validation result
?>

Hint:

Use a nested foreach structure: the outer loop iterates through form fields, and the inner loop checks each validation rule for that field. Collect errors in an array and display them at the end.

Exercise 3: CSV Data Processing

Create a script that processes CSV data using foreach loops:

<?php
// Start with this code template
// Simulated CSV data as an array
$csvData = [
    ["ID", "Name", "Department", "Salary", "Start Date"],
    ["101", "John Smith", "Marketing", "55000", "2021-03-15"],
    ["102", "Lisa Johnson", "HR", "62000", "2019-11-05"],
    ["103", "Michael Brown", "Development", "78000", "2020-06-22"],
    ["104", "Emily Davis", "Sales", "67000", "2022-01-10"],
    ["105", "Robert Wilson", "Development", "75000", "2020-08-17"]
];

// Use foreach loops to:
// 1. Convert the CSV data into an array of associative arrays with column headers as keys
// 2. Calculate average salary by department
// 3. Find the employee with the longest tenure
// 4. Format and display the data as an HTML table
?>

Hint:

First, extract the header row. Then use a foreach loop to convert each data row into an associative array using the headers as keys. Use additional foreach loops for the calculations, and a final loop to generate the HTML table.

Homework Assignment

Create a program that uses different types of loops

Develop a PHP application that demonstrates the use of foreach loops with arrays in at least three different scenarios:

  1. Create a file manager dashboard that lists files by type (images, documents, videos, etc.) and allows filtering by file extension.
  2. Implement a simple shopping cart system that calculates totals, applies discounts, and generates an order summary.
  3. Build a data analysis tool that processes a dataset (grades, sales, weather, etc.) and generates statistics and visualizations.

Requirements:

  • Use foreach loops for array processing in all three scenarios.
  • Demonstrate at least one nested foreach loop for handling multidimensional arrays.
  • Use at least one example of the reference operator (&) with a foreach loop.
  • Include meaningful comments explaining your code and its functionality.
  • Format your output with appropriate HTML and CSS.
  • Submit your code via the class GitHub repository by the next session.

Additional Resources

Coming Up Next

In our next session, we'll explore arrays in depth. We'll cover indexed arrays, associative arrays, multidimensional arrays, and the many array functions that PHP provides for searching, sorting, and manipulating array data. The foreach loops we've learned in this session will be essential tools as we work with these array types and operations.

Make sure to complete the homework assignment to reinforce your understanding of foreach loops before the next class!