Arrays7 min readExamples run on PHP 8.5.10

array_column()

Learn how array_column() pulls one column out of a list of arrays or objects, how to reindex results, which rows it skips, and the mistakes to avoid.

Signature

array_column(array $array, int|string|null $column_key, int|string|null $index_key = null): array
Available since PHP 5.5.07.48.08.18.28.38.48.5All versions →

Purpose

array_column() extracts one "column" from a list of rows. Each row is an array or an object, and the column is the entry (or public property) that you name in every row. It is the usual tool for turning a record set into a plain list of names, ids or prices, and for building lookup tables keyed by an identifier.

Signature

Parameters and defaults

  • $array: a list of rows. Each row should be an array or an object. For objects, public properties are read directly. A non-public property is only readable if the class implements both __get() and __isset().
  • $column_key: the integer key or string name of the value to collect. Pass null to keep each whole row instead of one value, which is mainly useful together with $index_key.
  • $index_key: optional, defaults to null. It names the column whose values become the keys of the result. The values are cast the way any array key is cast.

Return value and failure cases

The function always returns an array. Without $index_key it is a list with fresh keys 0, 1, 2, ...; the keys of the input are never preserved. With $column_key set to null, the rows themselves are returned.

Rows that are neither arrays nor objects, and rows that lack the requested entry, are skipped silently. No warning is raised, so a typo in the column name simply gives you an empty array.

Failures are rare but real:

  • If an index value in a row is an object, PHP 8.0 and later throw a TypeError instead of casting it to a string.
  • If a class provides __isset() but no __get(), reading a non-public property throws an Error.
  • If a class provides neither magic method, a non-public property is not readable and the object contributes nothing.

Example 1: a simple column

The most common use is extracting a single field from every record.

Example
<?php
$records = [
    ['id' => 2135, 'first_name' => 'John', 'last_name' => 'Doe'],
    ['id' => 3245, 'first_name' => 'Sally', 'last_name' => 'Smith'],
    ['id' => 5342, 'first_name' => 'Jane', 'last_name' => 'Jones'],
];

echo json_encode(array_column($records, 'first_name'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
["John","Sally","Jane"]

The result is a list in the same order as the input rows.

Example 2: indexing by another column

Add a third argument to key the result by a column. Passing null as the column key keeps the whole row, which gives you a quick lookup table by id.

Example
<?php
$records = [
    ['id' => 10, 'name' => 'Ada', 'role' => 'admin'],
    ['id' => 20, 'name' => 'Linus', 'role' => 'editor'],
    ['id' => 30, 'name' => 'Grace', 'role' => 'editor'],
];

$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
echo json_encode(array_column($records, 'name', 'id'), $flags), "\n";
echo json_encode(array_column($records, null, 'id'), $flags), "\n";
Output
{"10":"Ada","20":"Linus","30":"Grace"}
{"10":{"id":10,"name":"Ada","role":"admin"},"20":{"id":20,"name":"Linus","role":"editor"},"30":{"id":30,"name":"Grace","role":"editor"}}

Because the keys are integers that do not form a list starting at zero, json_encode() shows both results as JSON objects.

Example 3: skipped and incomplete rows

This example shows what happens with messy input.

Example
<?php
$rows = [
    ['sku' => 'A1', 'price' => 5],
    ['sku' => 'B2'],
    'oops',
    ['price' => 7],
    ['sku' => 'C3', 'price' => 0],
    null,
];

$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
echo json_encode(array_column($rows, 'price'), $flags), "\n";
echo json_encode(array_column($rows, 'price', 'sku'), $flags), "\n";
Output
[5,7,0]
{"A1":5,"0":7,"C3":0}

The B2 row has no price, and the string and null rows are not rows at all, so all three are skipped. A price of 0 is kept, because only a missing entry causes a skip. In the second call, the row without a sku still contributes its price, but it receives the next free integer key, here 0.

Edge cases

  • Duplicate index values: when two rows share the same index value, the later row overwrites the earlier one. Rows are lost without any notice.
  • Missing index entry: the value is appended with the next integer key, as Example 3 shows.
  • Empty input: an empty array returns an empty array.
  • Objects: public properties work out of the box. Since PHP 7.1, property visibility is respected, so private and protected properties need __isset() and __get().
  • Integer keys: for rows such as [10, 'Ada'], you can use 1 as the column key to get the second element of each row.

Common mistakes

  1. Expecting original keys to be preserved. The result is renumbered unless you supply $index_key.
  2. Mistyping the column name. Since missing entries are skipped silently, you get an empty array rather than an error. Check for an empty result when the data is untrusted.
  3. Using a non-unique index column. Indexing by something like a role or last name collapses rows. Group manually in a loop if you need several rows per key.
  4. Assuming 0 or empty strings are dropped. Only absent entries are skipped; falsy values stay.
  5. Relying on private properties. Without both magic methods, objects are skipped or an Error is thrown.
  6. Using an object as the index value. On PHP 8 this throws a TypeError.
  • array_map() transforms every element and can compute values that are not stored in a column.
  • array_combine() builds an array from separate lists of keys and values.
  • array_keys() and array_values() work with the keys and values of a single array.
  • array_filter() removes rows before you extract a column.
  • usort() and array_multisort() reorder rows by a column.

Recap

array_column() takes a list of array or object rows and returns the values of one column. Add an index key to build a lookup table, or use null as the column key to keep the full rows. Rows that are not arrays or objects, or that lack the entry, are skipped silently, duplicate index values overwrite each other, and original keys are never preserved.

Tested examples

Extract a single column from records
<?php
$records = [
    ['id' => 2135, 'first_name' => 'John', 'last_name' => 'Doe'],
    ['id' => 3245, 'first_name' => 'Sally', 'last_name' => 'Smith'],
    ['id' => 5342, 'first_name' => 'Jane', 'last_name' => 'Jones'],
];

echo json_encode(array_column($records, 'first_name'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
["John","Sally","Jane"]
Index the result by another column
<?php
$records = [
    ['id' => 10, 'name' => 'Ada', 'role' => 'admin'],
    ['id' => 20, 'name' => 'Linus', 'role' => 'editor'],
    ['id' => 30, 'name' => 'Grace', 'role' => 'editor'],
];

$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
echo json_encode(array_column($records, 'name', 'id'), $flags), "\n";
echo json_encode(array_column($records, null, 'id'), $flags), "\n";
Output
{"10":"Ada","20":"Linus","30":"Grace"}
{"10":{"id":10,"name":"Ada","role":"admin"},"20":{"id":20,"name":"Linus","role":"editor"},"30":{"id":30,"name":"Grace","role":"editor"}}
Skipped and incomplete rows
<?php
$rows = [
    ['sku' => 'A1', 'price' => 5],
    ['sku' => 'B2'],
    'oops',
    ['price' => 7],
    ['sku' => 'C3', 'price' => 0],
    null,
];

$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
echo json_encode(array_column($rows, 'price'), $flags), "\n";
echo json_encode(array_column($rows, 'price', 'sku'), $flags), "\n";
Output
[5,7,0]
{"A1":5,"0":7,"C3":0}