Home PHP PHP Arrays Explained — Types, Syntax, and Common Mistakes

PHP Arrays Explained — Types, Syntax, and Common Mistakes

In Plain English 🔥
Imagine you're packing for a road trip. Instead of carrying one item in each hand, you grab a suitcase and pack everything inside — shirts in one slot, shoes in another, snacks in a zip pocket. A PHP array is that suitcase: one variable that holds multiple values, each stored in its own labelled slot. Without arrays, you'd need a separate variable for every piece of data — like carrying each item of clothing loose in your arms. Nobody wants that.
⚡ Quick Answer
Imagine you're packing for a road trip. Instead of carrying one item in each hand, you grab a suitcase and pack everything inside — shirts in one slot, shoes in another, snacks in a zip pocket. A PHP array is that suitcase: one variable that holds multiple values, each stored in its own labelled slot. Without arrays, you'd need a separate variable for every piece of data — like carrying each item of clothing loose in your arms. Nobody wants that.

Every real application deals with lists. A shopping cart holds multiple products. A blog has multiple posts. A user profile stores multiple preferences. If PHP only let you store one value per variable, you'd be writing hundreds of lines just to hold a handful of items — and your code would collapse the moment the list grew or shrank. Arrays are how PHP solves this problem, and they're used in virtually every PHP script ever written.

The specific problem arrays fix is called 'data grouping'. Instead of writing $product1, $product2, $product3 and scrambling to keep track of them all, you write one $products array and let PHP manage the collection for you. You can add to it, remove from it, loop over it, sort it, search it — all with built-in tools PHP provides out of the box.

By the end of this article you'll know how to create all three types of PHP arrays (indexed, associative, and multidimensional), how to read and update values inside them, how to loop through them, and — crucially — the exact mistakes that trip up beginners so you can dodge them from day one.

Indexed Arrays — A Numbered List PHP Can Remember

An indexed array stores values in numbered slots, starting at position 0. Think of it like a numbered queue at a bakery: the first person is ticket 0, the second is ticket 1, and so on. The number is called the index or key, and the thing stored there is the value.

Why does counting start at 0? It's a convention inherited from low-level computing, and PHP follows it like almost every other language. It trips up beginners exactly once — then you never forget it.

You create an indexed array using the square-bracket syntax (preferred in modern PHP) or the older array() function. Both work, but square brackets are cleaner and what you'll see in professional codebases today.

To get a value out, you write the variable name followed by the index in square brackets: $fruits[0] gives you the first item. To add a new item to the end, use $fruits[] = 'mango' — the empty brackets tell PHP to append automatically. You don't need to know what the next index number is; PHP figures it out.

indexed_array_basics.php · PHP
12345678910111213141516171819202122232425262728293031323334353637
<?php

// Create an indexed array of fruit names
// PHP automatically assigns index 0, 1, 2 to each item
$fruits = ['apple', 'banana', 'cherry'];

// Access the first item — remember, counting starts at 0!
echo $fruits[0]; // apple
echo "\n";

// Access the third item using index 2
echo $fruits[2]; // cherry
echo "\n";

// Add a new item to the END of the array
// Empty [] tells PHP: 'put this at the next available index'
$fruits[] = 'mango';

// Count how many items are in the array
$totalFruits = count($fruits);
echo "Total fruits: " . $totalFruits; // 4
echo "\n";

// Loop through every item using a foreach loop
// $fruit (singular) is a temporary variable that holds each item one-by-one
foreach ($fruits as $fruit) {
    echo "- " . $fruit . "\n";
}

// Update an existing item — overwrite index 1
$fruits[1] = 'blueberry';
echo "Updated index 1: " . $fruits[1]; // blueberry
echo "\n";

// Print the full array structure for debugging
print_r($fruits);
▶ Output
apple
cherry
Total fruits: 4
- apple
- banana
- cherry
- mango
Updated index 1: blueberry
Array
(
[0] => apple
[1] => blueberry
[2] => cherry
[3] => mango
)
⚠️
Watch Out: Indexes Start at 0, Not 1If your array has 4 items, the last one is at index 3 — not 4. Trying to access $fruits[4] on a 4-item array gives you NULL and a Notice in PHP 8. Always use count($array) - 1 to safely grab the last item, or better yet, use the end() function.

Associative Arrays — Give Your Data a Meaningful Label

An indexed array is great for ordered lists, but what if you want to store a person's profile? You'd need to remember that index 0 is the name, index 1 is the email, index 2 is the age — and that's a disaster waiting to happen.

Associative arrays solve this by letting you choose your own keys instead of relying on numbers. Think of it like a form with labelled fields: 'Name: Sarah', 'Email: sarah@example.com', 'Age: 28'. Each label (key) maps directly to its value. This is how PHP stores structured data — user records, configuration settings, API responses.

You create an associative array using the same square-bracket syntax, but you define the key explicitly using the => arrow operator. On the left of => is the key (a string), on the right is the value.

Associative arrays are the backbone of most real PHP applications. When PHP reads a submitted HTML form, it hands you the data as an associative array in $_POST. When you decode a JSON API response, you get an associative array. When you fetch a database row with PDO, it comes back as an associative array. You'll use these constantly.

associative_array_basics.php · PHP
123456789101112131415161718192021222324252627282930313233343536373839404142
<?php

// Create an associative array to store a user's profile
// The string on the LEFT of => is the key
// The value on the RIGHT of => is what's stored
$userProfile = [
    'name'    => 'Sarah',
    'email'   => 'sarah@example.com',
    'age'     => 28,
    'country' => 'Canada'
];

// Access a value using its KEY — no index numbers needed
echo $userProfile['name'];    // Sarah
echo "\n";
echo $userProfile['email'];   // sarah@example.com
echo "\n";

// Update a value — same syntax, just assign a new value
$userProfile['age'] = 29;
echo "Updated age: " . $userProfile['age']; // 29
echo "\n";

// Add a brand new key-value pair at any time
$userProfile['role'] = 'editor';

// Loop through an associative array using foreach
// $key holds the label, $value holds the data
foreach ($userProfile as $key => $value) {
    echo $key . ': ' . $value . "\n";
}

// Check if a specific key EXISTS before using it
// This prevents errors when data might be missing
if (array_key_exists('email', $userProfile)) {
    echo "Email is set: " . $userProfile['email'] . "\n";
}

// Get all keys as a separate array
$profileKeys = array_keys($userProfile);
print_r($profileKeys);
▶ Output
Sarah
sarah@example.com
Updated age: 29
name: Sarah
email: sarah@example.com
age: 29
country: Canada
role: editor
Email is set: sarah@example.com
Array
(
[0] => name
[1] => email
[2] => age
[3] => country
[4] => role
)
⚠️
Pro Tip: Use array_key_exists() Before Accessing Unknown KeysIf you try to read $userProfile['phone'] and that key doesn't exist, PHP 8 throws a Warning and returns NULL silently — which can cause subtle bugs downstream. Always check with array_key_exists('phone', $userProfile) or the shorthand isset($userProfile['phone']) before accessing keys you're not 100% sure are there.

Multidimensional Arrays — Arrays Inside Arrays

So far each array has stored simple values — strings and numbers. But what if you want to store a list of users, and each user has their own profile data? You put arrays inside arrays. That's a multidimensional array, and it's less scary than it sounds.

Think of a spreadsheet. Each row is a user, each column is a piece of data (name, email, age). A multidimensional array works exactly the same way: the outer array is the list of rows, and each inner array is one row of data.

To access a value, you chain square brackets: $users[0]['name'] means 'go to the first user (index 0), then get the name key from their profile'. It reads left-to-right, outer-to-inner.

Multidimensional arrays are everywhere in PHP. Database query results return as an array of associative arrays. JSON from an API decodes into nested arrays. Shopping cart data is a list of product arrays. Once you're comfortable with one level of nesting, the rest follows the exact same logic — just add another bracket.

multidimensional_array_basics.php · PHP
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
<?php

// A list of users — each user is its own associative array
// The outer array uses automatic numeric indexes (0, 1, 2)
$users = [
    [
        'name'  => 'Alice',
        'email' => 'alice@example.com',
        'role'  => 'admin'
    ],
    [
        'name'  => 'Bob',
        'email' => 'bob@example.com',
        'role'  => 'editor'
    ],
    [
        'name'  => 'Carol',
        'email' => 'carol@example.com',
        'role'  => 'viewer'
    ]
];

// Access a single value — outer index first, then inner key
// Read as: "user at position 0, then their name"
echo $users[0]['name'];  // Alice
echo "\n";

// Access Bob's email: position 1, key 'email'
echo $users[1]['email']; // bob@example.com
echo "\n";

// Loop through all users and display a formatted summary
foreach ($users as $index => $user) {
    // $index is the numeric position (0, 1, 2)
    // $user is the full associative array for that person
    echo "User #" . ($index + 1) . ": " . $user['name'];
    echo " (" . $user['role'] . ")\n";
}

// Add a brand new user to the list
$users[] = [
    'name'  => 'Dave',
    'email' => 'dave@example.com',
    'role'  => 'editor'
];

echo "\nTotal users after adding Dave: " . count($users) . "\n";

// Update a nested value — change Carol's role
$users[2]['role'] = 'admin';
echo "Carol's new role: " . $users[2]['role'] . "\n";
▶ Output
Alice
bob@example.com
User #1: Alice (admin)
User #2: Bob (editor)
User #3: Carol (viewer)

Total users after adding Dave: 4
Carol's new role: admin
🔥
Interview Gold: How Deep Can Arrays Nest?PHP has no hard limit on nesting depth — you can have arrays inside arrays inside arrays. But in practice, if you're going beyond 2-3 levels deep, it's a signal your data structure might need rethinking (or converting to objects). Interviewers love asking this to see if you think about code maintainability, not just whether it works.

The Most Useful PHP Array Functions You'll Actually Use

PHP ships with over 70 built-in array functions. You don't need to memorise all of them — but a handful come up in almost every project. Knowing these saves you from writing loops by hand for tasks PHP already solved.

Here's the honest shortlist: count() tells you how many items are in an array. in_array() checks whether a value exists anywhere in an array. array_push() adds items to the end (though the [] shorthand is more common). array_pop() removes and returns the last item. array_merge() combines two arrays into one. array_filter() removes items that don't pass a test. array_map() transforms every item using a function. sort() sorts an indexed array alphabetically or numerically. ksort() sorts an associative array by its keys.

The most important mental model: some functions return a new array (array_map, array_filter, array_merge) while others modify the original array in place (sort, ksort, array_push). This distinction matters — if you expect a sorted copy but get NULL because you forgot to use the return value, you'll be confused for longer than you should be.

array_functions_essentials.php · PHP
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
<?php

$temperatures = [22, 18, 31, 15, 27, 9, 34];

// --- count() ---
// Returns the total number of items
echo "Days recorded: " . count($temperatures) . "\n"; // 7

// --- in_array() ---
// Returns true if the value exists somewhere in the array
if (in_array(31, $temperatures)) {
    echo "31 degrees was recorded\n";
}

// --- sort() ---
// Sorts the array in place, lowest to highest
// WARNING: this MODIFIES the original array — it does NOT return a new one
sort($temperatures);
echo "Sorted temperatures: ";
echo implode(', ', $temperatures) . "\n"; // 9, 15, 18, 22, 27, 31, 34

// --- array_filter() ---
// Keeps only the items where the callback returns true
// Does NOT modify the original — returns a NEW array
$hotDays = array_filter($temperatures, function($temp) {
    return $temp >= 25; // Keep only temperatures 25 and above
});
echo "Hot days (25+): ";
echo implode(', ', $hotDays) . "\n"; // 27, 31, 34

// --- array_map() ---
// Transforms EVERY item using a function — returns a NEW array
$celsiusTemps = [0, 20, 37, 100];
$fahrenheitTemps = array_map(function($celsius) {
    return ($celsius * 9/5) + 32; // Convert Celsius to Fahrenheit
}, $celsiusTemps);
echo "Fahrenheit: ";
echo implode(', ', $fahrenheitTemps) . "\n"; // 32, 68, 98.6, 212

// --- array_merge() ---
// Combines two arrays into one new array
$morningReadings = [18, 19, 21];
$afternoonReadings = [28, 31, 29];
$allReadings = array_merge($morningReadings, $afternoonReadings);
echo "All readings: ";
echo implode(', ', $allReadings) . "\n"; // 18, 19, 21, 28, 31, 29

// --- array_pop() ---
// Removes AND returns the last item — modifies the original array
$lastReading = array_pop($allReadings);
echo "Removed last reading: " . $lastReading . "\n"; // 29
echo "Remaining count: " . count($allReadings) . "\n"; // 5
▶ Output
Days recorded: 7
31 degrees was recorded
Sorted temperatures: 9, 15, 18, 22, 27, 31, 34
Hot days (25+): 27, 31, 34
Fahrenheit: 32, 68, 98.6, 212
All readings: 18, 19, 21, 28, 31, 29
Removed last reading: 29
Remaining count: 5
⚠️
Pro Tip: sort() Returns Bool, Not the Sorted ArrayThis catches everyone once. sort($myArray) returns true on success — NOT the sorted array. The sorted result is in $myArray itself. So $sorted = sort($myArray) gives you true in $sorted, not what you want. Just call sort($myArray) on its own line, then use $myArray.
FeatureIndexed ArrayAssociative ArrayMultidimensional Array
Key typeAuto-assigned integers (0, 1, 2...)Custom strings or integers you defineMix of both — outer and inner can differ
Best used forOrdered lists with no named fields (e.g. a list of tags)Structured records with named fields (e.g. user profile)Collections of structured records (e.g. database rows)
Access syntax$tags[0]$user['email']$users[0]['email']
Add new item$tags[] = 'php'$user['phone'] = '555-1234'$users[] = ['name' => 'Eve']
Loop styleforeach ($tags as $tag)foreach ($user as $key => $value)foreach ($users as $user) then access $user['key']
Common real-world useList of category names, image URLsForm POST data, config settings, API response fieldsDatabase result sets, JSON API responses, cart items

🎯 Key Takeaways

  • PHP has three practical array types — indexed (numbered slots), associative (named keys), and multidimensional (nested arrays) — and each solves a different data-storage problem.
  • Indexed arrays start at 0, not 1. The last item in a 5-element array is at index 4. Getting this wrong is the single most common beginner bug.
  • sort(), array_push(), and array_pop() modify the original array directly — they do not return a new copy. array_map() and array_filter() return new arrays and leave the original untouched.
  • Always use array_key_exists() or isset() before accessing an associative array key you're not certain exists — silent NULL returns and PHP Warnings are far harder to debug than a proactive check.

⚠ Common Mistakes to Avoid

  • Mistake 1: Off-by-one index errors — Accessing $items[count($items)] instead of $items[count($items) - 1] to get the last item. Since arrays start at index 0, a 5-item array has a last index of 4, not 5. Accessing index 5 returns NULL and triggers a PHP Notice. Fix: use $items[count($items) - 1] or the built-in end($items) function which safely returns the last element without needing to know the index.
  • Mistake 2: Forgetting that sort() modifies the original array in place — Beginners write $sorted = sort($prices) expecting a sorted copy in $sorted. Instead, $sorted gets true (the boolean return value of sort), and $prices itself is now sorted. Fix: call sort($prices) on its own line with no assignment, then read from $prices. If you need to keep the original order intact, copy the array first with $sortedPrices = $prices; sort($sortedPrices);
  • Mistake 3: Using == instead of === when searching arrays — in_array('1', [1, 2, 3]) returns true with loose comparison (==) because PHP coerces the string '1' to the integer 1. This causes phantom matches that are very hard to debug. Fix: always pass true as the third argument — in_array('1', [1, 2, 3], true) — to enable strict type-safe comparison. It returns false because a string is not strictly equal to an integer.

Interview Questions on This Topic

  • QWhat's the difference between an indexed array and an associative array in PHP, and when would you choose one over the other?
  • QIf you call sort() on an associative array in PHP, what happens to the keys — and what function would you use instead if you want to sort by key while preserving the key-value pairs?
  • QWhat does array_map() return versus what does array_walk() return — and which one would you use if you need to transform every value in an array into a new array of results?

Frequently Asked Questions

What is the difference between array() and [] in PHP?

They do exactly the same thing — both create an array. The square bracket syntax [] was introduced in PHP 5.4 and is now the modern standard you'll see in every professional codebase. array() still works perfectly, but [] is shorter and cleaner. Use [] unless you're maintaining code on an ancient PHP version below 5.4.

How do I check if a value exists in a PHP array?

Use in_array($value, $array) for a simple existence check — it returns true or false. For associative arrays where you want to check if a KEY exists (not a value), use array_key_exists('keyName', $array) or isset($array['keyName']). The key difference: isset() also returns false if the key exists but its value is NULL, while array_key_exists() returns true in that case.

Why does PHP use 0 as the first index of an array instead of 1?

Zero-based indexing comes from how computer memory addressing works at a low level — the index represents an offset from the start of the data block, and the first item has no offset, so it's 0. PHP inherits this convention from C, as do JavaScript, Python, Java, and most other languages. It feels odd at first but becomes completely natural within a week of practice.

🔥
TheCodeForge Editorial Team Verified Author

Written and reviewed by senior developers with real-world experience across enterprise, startup and open-source projects. Every article on TheCodeForge is written to be clear, accurate and genuinely useful — not just SEO filler.

← PreviousPHP FunctionsNext →PHP Strings and String Functions
Forged with 🔥 at TheCodeForge.io — Where Developers Are Forged