PHP · Beginner

Arrays in PHP

9 min readUpdated September 24, 2026Every example verified

In short: A PHP array is an ordered map that works as a list when its keys are 0, 1, 2 and so on: [10, 20, 30]. Read an element with $a[0], append with $a[] = $value, count with count($a) and walk it with foreach. Arrays are values: assigning or passing one makes an independent copy. Arrays with string keys are covered in the lesson on associative arrays.

One structure for lists and more

PHP has a single array type that covers what other languages split into lists, maps and stacks. Under the surface every array maps keys to values and remembers insertion order. When you write ["pear", "fig"] the keys are assigned automatically as 0 and 1, and the array behaves as a list; this lesson is about that use. Arrays whose keys are strings are the subject of the associative arrays lesson.

Read an element with its index in square brackets, starting from 0. Reading an index that does not exist yields null and a warning, so the last element of a list is $a[count($a) - 1], not $a[count($a)]. Assign to an index to replace an element. The shortest way to append is $a[] = $value, which uses the next integer key; array_push($a, $x, $y) appends several at once. array_pop removes and returns the last element, array_shift the first, and array_unshift inserts at the front. count($a) gives the number of elements.

foreach ($a as $value) visits every element in order; foreach ($a as $index => $value) also gives the key. Inside the loop $value is a copy, so assigning to it does not change the array. A for loop with an index is only needed when you must count or step differently.

Arrays are copied on assignment and when passed to a function. $b = $a; $b[] = 1; leaves $a unchanged. This is a real difference from languages where lists are references, and it is why a function that wants to change the caller's array must either return the new array or take a & reference parameter. (Internally PHP shares the storage until one side writes, so the copy is cheap.)

Removing with unset($a[1]) deletes the element but leaves the other keys as they were, so the array now has keys 0 and 2 and is no longer a tidy list. array_values($a) renumbers it. json_encode shows the difference at a glance: a list prints as [4,2], an array with gaps as {"0":4,"2":2}.

A few functions do most everyday list work. in_array($needle, $a) answers whether a value is present; array_search returns its index or false. array_sum, max and min summarise numbers. array_slice($a, $start, $length) extracts a run. implode(", ", $a) joins elements into a string and explode splits one. array_map($fn, $a) builds a new array by applying a function to each element, and array_filter($a, $fn) keeps the elements for which the function returns true, preserving their keys. Arrays can nest: $grid[1][2] reads row 1, column 2 of an array of arrays.

Syntax

 PHP · syntax
$list = ["pear", "fig", "plum"];   // keys 0, 1, 2
$empty = [];

$first = $list[0];
$last = $list[count($list) - 1];
$list[1] = "date";          // replace
$list[] = "lime";           // append with the next key
array_push($list, "kiwi", "apple");
$gone = array_pop($list);   // remove last

foreach ($list as $item) { ... }
foreach ($list as $i => $item) { ... }

count($list);  in_array("fig", $list);  array_search("fig", $list);
array_sum($nums);  max($nums);  min($nums);
array_slice($list, 1, 2);  array_reverse($list);
implode(", ", $list);  explode(",", "a,b,c");
array_map(fn($x) => $x * 2, $nums);
array_filter($nums, fn($x) => $x > 10);
$grid = [[1, 2], [3, 4]];  $grid[1][0];   // 3

Indexes start at 0. unset() leaves a gap; array_values() renumbers.

Building and reading a list

A bike repair shop keeps its queue of jobs in an array, appends new ones, takes the first, and lists the rest.

 PHP
<?php
$queue = ["bike 41", "bike 17"];
$queue[] = "bike 88";
array_push($queue, "bike 5", "bike 62");

echo count($queue), " jobs waiting\n";
echo "First: ", $queue[0], "\n";
echo "Last: ", $queue[count($queue) - 1], "\n";

$next = array_shift($queue);
echo "Now working on ", $next, "\n";
foreach ($queue as $position => $job) {
    echo $position + 1, ". ", $job, "\n";
}

Output

5 jobs waiting
First: bike 41
Last: bike 62
Now working on bike 41
1. bike 17
2. bike 88
3. bike 5
4. bike 62

Two elements come from the literal, one from $queue[] and two from array_push, giving five. The last element sits at index 4, which is count - 1. array_shift removes the front element and, for a list, renumbers the rest from 0, so the foreach keys run 0 to 3 and adding 1 gives a human-friendly position.

Reading numbers into an array and summarising

The first input line says how many parcel weights follow; the program collects them and reports totals.

 PHP
<?php
$n = (int) trim(fgets(STDIN));
$weights = [];
for ($i = 0; $i < $n; $i++) {
    $weights[] = (float) trim(fgets(STDIN));
}

echo "Total: ", array_sum($weights), "\n";
echo "Heaviest: ", max($weights), "\n";
echo "Average: ", round(array_sum($weights) / count($weights), 2), "\n";
$heavy = array_filter($weights, fn($w) => $w > 10);
echo "Over 10 kg: ", count($heavy), "\n";
echo implode(" | ", $weights), "\n";

Input given to the program: 412.581015.25

Output

Total: 45.75
Heaviest: 15.25
Average: 11.44
Over 10 kg: 2
12.5 | 8 | 10 | 15.25

The loop runs exactly $n times, appending one converted value per pass; this is the standard way to read a known number of items. array_filter receives an arrow function and returns only the elements over 10, so counting the result answers the question. implode joins the floats with a separator; 8 and 10 print without decimals because they are whole.

Copies, gaps and transformations

Assigning an array copies it, unset leaves a hole, and array_map builds a new array from an old one.

 PHP
<?php
$prices = [4, 9, 2];
$copy = $prices;
$copy[] = 7;
echo count($prices), " vs ", count($copy), "\n";

unset($prices[1]);
echo json_encode($prices), "\n";
$prices = array_values($prices);
echo json_encode($prices), "\n";

$doubled = array_map(fn($p) => $p * 2, $copy);
echo implode(",", $doubled), "\n";
echo in_array(9, $copy) ? "9 found" : "9 missing", "\n";
var_dump(array_search(7, $copy));
echo json_encode(array_slice($copy, 1, 2)), "\n";

Output

3 vs 4
{"0":4,"2":2}
[4,2]
8,18,4,14
9 found
int(3)
[9,2]

Appending to $copy does not touch $prices, which still has three elements. After unset($prices[1]) the keys are 0 and 2, and json_encode has to print it as an object to preserve them; array_values restores a list. array_map leaves $copy alone and returns the doubled values. array_search finds 7 at index 3, and array_slice takes two elements starting at index 1.

Common mistakes

  • Reading one past the end

    Why it goes wrong: $a[count($a)] does not exist because indexes start at 0. PHP prints a warning and gives null, and any arithmetic on it treats it as 0.

    Fix: Use $a[count($a) - 1], end($a) or $a[array_key_last($a)].

  • Assuming unset renumbers the array

    Why it goes wrong: After unset($a[0]) the first element has key 1; $a[0] is undefined and a for loop from 0 to count - 1 misses the last element.

    Fix: Call array_values after removing elements, or remove with array_splice, or use foreach, which ignores gaps.

     PHP · fix
    <?php
    $a = ["x", "y", "z"];
    unset($a[0]);
    $a = array_values($a);
    echo $a[0], "\n";   // y
  • Expecting a function to change the array it received

    Why it goes wrong: Arrays are passed by value. function add(array $a) { $a[] = 1; } changes a copy, and the caller's array is unchanged.

    Fix: Return the modified array and assign it, or declare the parameter as array &$a.

  • Leaving a reference alive after foreach by reference

    Why it goes wrong: After foreach ($a as &$v), $v still points at the last element, and a later loop that assigns to $v overwrites that element.

    Fix: Call unset($v) right after the loop, or avoid & and build a new array with array_map.

Everyday array functions

FunctionDoesReturns
count($a)number of elementsint
in_array($x, $a)is $x presentbool
array_search($x, $a)index of $xint or false
array_sum($a) / max($a) / min($a)summaries of numbersnumber
array_slice($a, $i, $len)a run of elementsnew array
array_map($fn, $a)apply $fn to eachnew array, same keys
array_filter($a, $fn)keep elements where $fn is truenew array, original keys
implode($sep, $a)join into textstring
array_values($a)renumber from 0new array

Where you use this

Most exercises hand you a sequence of values and ask for something about the whole: the sum, the largest, how many pass a test, or the same values transformed. The pattern is always the same: read the values into an array, then use array_sum, max, array_filter or array_map rather than tracking running totals by hand. Reading everything first also lets you make two passes, for example finding the average and then counting how many values are above it, which a single streaming loop cannot do.

 PHP · in practice
$lines = [];
while (($line = fgets(STDIN)) !== false) {
    $lines[] = (int) trim($line);
}
$avg = array_sum($lines) / count($lines);
echo count(array_filter($lines, fn($v) => $v > $avg)), "\n";

Key points

  • [a, b, c] creates a list with keys 0, 1, 2; $a[i] reads and writes; $a[] = x appends.
  • count gives the size; the last index is count - 1.
  • foreach visits elements in order, optionally with their keys.
  • Assigning or passing an array copies it; use & or return a new array to change the caller's.
  • unset leaves gaps; array_values renumbers.
  • array_map transforms, array_filter selects, array_sum/max/min summarise, implode joins.
  • Arrays nest: $grid[row][col].

Try it yourself

The program reads a count and then that many integers into $nums, then prints them in the order given. Change the last line so it prints them in reverse order, separated by single spaces.

Your program
<?php
$n = (int) trim(fgets(STDIN));
$nums = [];
for ($i = 0; $i < $n; $i++) {
    $nums[] = (int) trim(fgets(STDIN));
}
echo implode(" ", $nums), "\n";
Input the program receives: 3 ↵ 5 ↵ 1 ↵ 9
Expected output: 9 1 5

Practise this

Open the PHP playground

Frequently asked questions

Is a PHP array a list or a map?

Both. Every PHP array is an ordered map from keys to values. When the keys are 0, 1, 2 and so on it behaves as a list, and functions such as array_push and json_encode treat it as one. When the keys are strings, or integers with gaps, it behaves as a map. array_is_list($a) (PHP 8.1) tells you which case you have.

How do I check whether a PHP array is empty?

count($a) === 0 is explicit; empty($a) and !$a also work because an empty array is false in a condition. Note that [0] and [null] are not empty: they contain one element.

How do I remove an element from a PHP array?

unset($a[$i]) removes the element with that key and leaves the other keys unchanged, so follow it with array_values($a) when you need a list. array_splice($a, $i, 1) removes and renumbers in one step. array_pop and array_shift remove from the ends. To remove by value, find the key with array_search first, or use array_filter to build a new array without it.

Progress is stored only in this browser.

How this page was checked. Every program on it was run with PHP 8.4 at build time by the publishing checks, and the output shown is what it printed. Running PHP inside the browser is not available yet, so the Run button is absent rather than pretending; copy the code and run it with PHP 8.4 locally.