<< Home

Chapter 8: Arrays and Collections

Arrays are PHP’s fundamental data structure. They can act as lists, dictionaries, sets, stacks, or queues. Higher-level constructs such as iterators, generators, and SPL data structures build on this foundation to handle data efficiently and clearly.

Creating and Manipulating Arrays

Arrays can be indexed (numeric keys) or associative (string keys). You can create them with short syntax [] or the older array() form.

Defining indexed and associative arrays

Indexed arrays store values in numeric order, while associative arrays map keys to values. Choosing the right type keeps your data model simple and helps clarify whether position or meaning matters more for your elements.

<?php
$colors = ["red", "green", "blue"];
$user = ["name" => "Alice", "age" => 30];
?>

Adding, updating, and removing elements

Arrays are flexible containers that can grow or shrink as needed. Appending, assigning, or unsetting elements lets you adjust data dynamically in response to user input or program state.

<?php
$colors[] = "yellow";              // append
$user["email"] = "a@example.com";  // add new key
unset($user["age"]);               // remove
?>

Combining arrays and spreading

Use the union operator or spread syntax to merge arrays into one.

<?php
$a = ["a" => 1, "b" => 2];
$b = ["b" => 3, "c" => 4];
$merged = $a + $b;         // keeps first value of "b"
$spread = [...$a, ...$b];  // overwrites "b"
?>
💡 The union operator (+) preserves keys from the left array, while the spread syntax overwrites keys with later values.

Iterating over arrays

Use foreach to traverse arrays easily.

<?php
foreach ($user as $key => $value) {
  echo "$key = $value" . PHP_EOL;
}
?>

array_map, array_filter, array_reduce

These functional-style helpers transform, filter, and combine arrays without manual loops. They are expressive and concise when used with arrow functions or closures.

Transforming values with array_map()

array_map() applies a callback to every element of an array and returns a new array of transformed values. This encourages declarative programming by expressing what should happen to each value rather than how to loop through it.

<?php
$nums = [1, 2, 3];
$squares = array_map(fn($n) => $n ** 2, $nums);
print_r($squares);
?>

Filtering elements with array_filter()

array_filter() removes elements that do not meet a condition, returning only those that do. It is a concise way to clean data sets or apply logical tests without manual iteration.

<?php
$values = [1, 2, 3, 4, 5];
$even = array_filter($values, fn($n) => $n % 2 === 0);
print_r($even);
?>
⚠️ By default, array_filter() preserves keys. Use array_values() if you need consecutive numeric indices afterward.

Combining values with array_reduce()

array_reduce() accumulates all elements of an array into a single result, such as a total or concatenated string. It abstracts the common “reduce” pattern found in functional programming, making aggregation simpler and clearer.

<?php
$nums = [2, 3, 4];
$product = array_reduce($nums, fn($carry, $n) => $carry * $n, 1);
echo $product; // 24
?>
💡 array_reduce() is ideal for totals, concatenations, or any accumulation pattern where you combine values into one result.

Sorting and Slicing

PHP offers several functions to order, slice, and partition arrays. Choose the function that preserves or reindexes keys based on your needs.

Sorting arrays by value

Sorting reorders arrays so elements appear in numeric or alphabetical sequence. sort() discards keys and creates a clean index, useful for lists where order matters more than labels.

<?php
$nums = [4, 2, 8, 6];
sort($nums);
print_r($nums); // [2,4,6,8]
?>

Sorting while preserving keys

When keys carry meaning, use key-preserving sorts such as asort() or arsort(). These maintain associations between keys and values while reordering based on value comparisons.

<?php
$prices = ["apple" => 1.2, "pear" => 1.0, "plum" => 2.0];
asort($prices);
print_r($prices);
?>

Custom sorting with usort()

Provide a comparison function that returns negative, zero, or positive values to control ordering.

<?php
$words = ["pear", "banana", "apple"];
usort($words, fn($a, $b) => strlen($a) <=> strlen($b));
print_r($words);
?>

Extracting parts of arrays

array_slice() returns a portion of an array without changing the original. It is perfect for pagination, previews, or working on subsets of data without duplication or side effects.

<?php
$items = ["a", "b", "c", "d"];
print_r(array_slice($items, 1, 2)); // b, c
?>
💡 Combine array_slice() and array_splice() to take and modify portions of arrays in one step.

Iterators and Generators

Iterators provide a consistent interface to traverse data sources. Generators create lightweight iterators without building full arrays in memory.

Using built-in iterator interfaces

SPL iterators wrap collections in objects that support standard traversal methods. They provide uniform behavior for arrays, directory listings, and custom classes, simplifying integration with loops and higher-order functions.

<?php
$arr = new ArrayIterator(["a", "b", "c"]);
foreach ($arr as $item) {
  echo $item;
}
?>

Creating generators with yield

A generator function yields one value at a time. Each yield pauses the function, preserving local state until the next iteration.

<?php
function countdown(int $from) {
  while ($from > 0) {
    yield $from--;
  }
}

foreach (countdown(3) as $n) {
  echo $n . " ";
}
?>

Combining generators and pipelines

Generators compose neatly, allowing you to process streams lazily.

<?php
function squares(iterable $nums): iterable {
  foreach ($nums as $n) {
    yield $n * $n;
  }
}

foreach (squares(countdown(4)) as $sq) {
  echo $sq . " ";
}
?>
⚠️ Generators are single-pass; once you exhaust a generator, you must recreate it to iterate again.

SPL Data Structures

The Standard PHP Library (SPL) provides object-based collections for stacks, queues, heaps, and more. They are efficient alternatives to plain arrays for specific use cases.

Using SplStack and SplQueue

SplStack and SplQueue implement efficient push/pop and enqueue/dequeue operations. They are ideal for managing ordered data where the access pattern strictly follows last-in-first-out or first-in-first-out rules.

<?php
$stack = new SplStack();
$stack->push("a");
$stack->push("b");
echo $stack->pop(); // b

$queue = new SplQueue();
$queue->enqueue("x");
$queue->enqueue("y");
echo $queue->dequeue(); // x
?>

Working with SplHeap and SplPriorityQueue

Heaps and priority queues maintain items in order of priority instead of insertion. These data structures are useful for scheduling, ranking, and any process that must always access the most important element first.

<?php
$heap = new SplMinHeap();
$heap->insert(5);
$heap->insert(2);
$heap->insert(8);

foreach ($heap as $val) {
  echo $val . " ";
}
?>
💡 SPL structures implement Iterator, Countable, and ArrayAccess, allowing them to work seamlessly in loops and functions that expect arrays.

Choosing between SPL and arrays

StructureBest forNotes
SplStackLIFO operationspush / pop
SplQueueFIFO operationsenqueue / dequeue
SplHeapPriority orderingmin or max heaps
SplFixedArrayFixed-size numeric arraysLower memory overhead

Destructuring with List Syntax

PHP can unpack arrays directly into variables using list syntax. This is useful for tuples or predictable small collections.

Using list() for numeric arrays

The list() construct unpacks arrays into individual variables by position. It reads naturally when dealing with small fixed-length arrays that represent tuples or coordinate pairs.

<?php
$coords = [10, 20];
list($x, $y) = $coords;
echo "X=$x, Y=$y";
?>

Using short array destructuring syntax

Short array destructuring provides a concise alternative to list(). It improves readability and pairs well with modern PHP style, especially when assigning multiple values in a single statement.

<?php
[$r, $g, $b] = [255, 128, 64];
echo "R=$r G=$g B=$b";
?>

Destructuring associative arrays with named keys

From PHP 7.1 onward, you can destructure associative arrays by key name.

<?php
$user = ["id" => 5, "name" => "Kai"];
["id" => $id, "name" => $name] = $user;
echo "$id: $name";
?>
💡 Use destructuring when functions return arrays with known positions or keys; it reduces boilerplate and clarifies intent.