Access Array Items
How Array Access Works
In simple terms: To read a value from an array, you write the array's name followed by the item's key in square brackets: $fruits[0] or $user['email'].
Technically: The array access operator [] looks up a key in the array's hash table and returns the associated value. For nested arrays, each additional pair of brackets looks up a key in the result of the previous lookup. Accessing a key that does not exist returns null and raises a warning.
Accessing by Index and by Key
<?php
$fruits = ['Mango', 'Banana', 'Guava'];
$user = ['name' => 'Asha', 'email' => 'asha@example.com'];
echo $fruits[0] . "\n";
echo $fruits[2] . "\n";
echo $user['email'] . "\n";
Output
Mango
Guava
asha@example.com
- Indexed arrays use integer positions starting at
0. - Associative arrays use their string keys. Keys are case-sensitive:
$user['Email']is a different (missing) key.
Using Variables and Expressions as Keys
<?php
$prices = ['small' => 99, 'medium' => 149, 'large' => 199];
$selectedSize = 'medium';
echo $prices[$selectedSize] . "\n";
$fruits = ['Mango', 'Banana', 'Guava'];
$position = 1;
echo $fruits[$position + 1] . "\n";
Output
149
Guava
The key can be any expression: a variable, a calculation, or a function result. This is how code reads values chosen at runtime, such as the size a user selected.
Accessing Nested Arrays
Each pair of brackets goes one level deeper:
<?php
$order = [
'id' => 501,
'customer' => [
'name' => 'Asha',
'address' => ['city' => 'Madurai', 'pin' => '625001'],
],
'items' => [
['name' => 'Gel Pen', 'qty' => 10],
['name' => 'Notebook', 'qty' => 3],
],
];
echo $order['customer']['name'] . "\n";
echo $order['customer']['address']['city'] . "\n";
echo $order['items'][1]['name'] . "\n";
echo "Items in order: " . count($order['items']) . "\n";
Output
Asha
Madurai
Notebook
Items in order: 2
Reading the Path
$order['items'][1]['name'] means:
$order['items']— the list of items[1]— the second item in that list['name']— that item's name
Reading the brackets from left to right describes the path through the data.
Accessing Values Inside Strings
<?php
$user = ['name' => 'Asha', 'plan' => 'Pro'];
$scores = [88, 92];
echo "Welcome, {$user['name']}! Your plan: {$user['plan']}\n";
echo "First score: $scores[0]\n";
Output
Welcome, Asha! Your plan: Pro
First score: 88
Use curly braces for quoted string keys and for nested access. See String Interpolation.
Missing Keys
What Happens
<?php
$user = ['name' => 'Asha'];
$phone = $user['phone'];
var_dump($phone);
Output
PHP Warning: Undefined array key "phone" in /path/script.php on line 4
NULL
PHP raises a warning and uses null. The script continues, which can lead to wrong output later (for example, an empty phone field in an email).
Safe Access With ??
<?php
$user = ['name' => 'Asha'];
echo $user['phone'] ?? 'Not provided';
echo "\n";
echo $user['address']['city'] ?? 'City unknown';
echo "\n";
Output
Not provided
City unknown
?? checks the whole path without warnings, even when an intermediate level (address) is missing. It is the standard way to read optional data.
Checking First
| Check | true When |
|---|---|
isset($array['key']) | The key exists and its value is not null |
array_key_exists('key', $array) | The key exists (value may be null) |
!empty($array['key']) | The key exists and its value is truthy |
<?php
$form = ['name' => 'Asha', 'nickname' => null, 'age' => '0'];
var_dump(isset($form['nickname']));
var_dump(array_key_exists('nickname', $form));
var_dump(!empty($form['age']));
Output
bool(false)
bool(true)
bool(false)
Note the empty() trap: '0' counts as empty, even though an age of zero could be a real answer.
Accessing Keys on Non-Arrays
<?php
$user = null; // for example, a database lookup that found nothing
echo $user['name'];
Output
PHP Warning: Trying to access array offset on value of type null in /path/script.php on line 4
Functions that "usually" return an array may return null or false when nothing is found. Check the result first, or use $user['name'] ?? 'Guest', which handles a null array as well.
First and Last Elements
<?php
$queue = ['ORD-11', 'ORD-12', 'ORD-13'];
$prices = ['pen' => 20, 'book' => 250, 'bag' => 1299];
echo $queue[0] . "\n";
echo $queue[array_key_last($queue)] . "\n";
echo array_key_first($prices) . "\n";
echo $prices[array_key_last($prices)] . "\n";
Output
ORD-11
ORD-13
pen
1299
| Function | Returns | Available Since |
|---|---|---|
array_key_first($array) | The first key (null if empty) | PHP 7.3 |
array_key_last($array) | The last key (null if empty) | PHP 7.3 |
array_first($array) | The first value (null if empty) | PHP 8.5 |
array_last($array) | The last value (null if empty) | PHP 8.5 |
reset($array) / end($array) | First / last value, but moves the internal pointer | Old API |
array_key_first() and array_key_last() work for any keys, including associative arrays and lists with gaps, unlike $array[0] or $array[count($array) - 1].
Extracting One Field From Records
array_column() reads the same key from every record:
<?php
$students = [
['id' => 11, 'name' => 'Asha', 'score' => 88],
['id' => 12, 'name' => 'Bala', 'score' => 72],
['id' => 13, 'name' => 'Charu', 'score' => 95],
];
echo implode(', ', array_column($students, 'name')) . "\n";
$scoresById = array_column($students, 'score', 'id');
echo $scoresById[13] . "\n";
Output
Asha, Bala, Charu
95
array_column($records, 'name')returns a list of names.- With a third argument,
array_column($records, 'score', 'id')uses one field as the key and another as the value — a quick way to build a lookup table.
Practical Example: Reading Nested Data by Path
APIs often return deeply nested data where some fields may be missing. A small helper can read a value by a dot-separated path and fall back to a default:
<?php
function arrayGet(array $data, string $path, mixed $default = null): mixed
{
foreach (explode('.', $path) as $segment) {
if (!is_array($data) || !array_key_exists($segment, $data)) {
return $default;
}
$data = $data[$segment];
}
return $data;
}
$order = [
'id' => 501,
'customer' => ['name' => 'Asha', 'address' => ['city' => 'Madurai']],
'items' => [['name' => 'Gel Pen', 'qty' => 10], ['name' => 'Notebook', 'qty' => 3]],
];
var_dump(arrayGet($order, 'customer.address.city'));
var_dump(arrayGet($order, 'items.1.qty'));
var_dump(arrayGet($order, 'customer.phone', 'N/A'));
var_dump(arrayGet($order, 'id.extra', 'N/A'));
Output
string(7) "Madurai"
int(3)
string(3) "N/A"
string(3) "N/A"
Step-by-Step Explanation
- The path is split into segments:
'items.1.qty'becomes['items', '1', 'qty']. - For each segment, the function checks that the current value is an array and contains the key, then moves one level deeper.
- If any step fails, it returns the default instead of raising a warning.
- The segment
'1'is a string, but PHP treats the integer-like string key'1'and the integer key1as the same key, soarray_key_exists('1', ...)finds the second item. 'id.extra'stops safely because501is not an array.
array_key_exists() is used instead of isset() so that keys whose value is null are returned as null, not replaced by the default. Laravel provides the same idea as the helper data_get().
Common Mistakes
Off-by-One Indexes
Effect: $list[count($list)] reads past the end.
Fix: The last index is count($list) - 1, or use array_key_last().
Wrong Key Case or Spelling
Effect: $user['Email'] is undefined when the key is 'email'.
Fix: Use consistent key names, ideally defined in one place.
Reading Optional Keys Directly
Effect: Warnings and null values spreading through the code.
Fix: Use ?? with a sensible default.
Accessing Results Without Checking Them
Effect: "Trying to access array offset on value of type null/bool".
Fix: Check the result (if ($row === null)) or use ??.
Using empty() to Test for Presence
Effect: Valid values like 0 or '0' are treated as missing.
Fix: Use isset(), array_key_exists(), or explicit comparisons.
Best Practices
- Read required keys directly and optional keys with
??. - Use
array_key_exists()whennullis a meaningful value. - Use
array_key_first()/array_key_last()(orarray_first()/array_last()in PHP 8.5+) instead of index arithmetic. - Use
array_column()to extract fields from lists of records. - Validate data from outside sources before relying on its structure.
Official reference: https://www.php.net/manual/en/language.types.array.php#language.types.array.syntax.accessing