php language basics
Arrays
An array is a value that can hold many values. In PHP, the same array type is used for simple lists, key-value maps, and nested records. That flexibility is useful, but it also means you must be clear about the shape of the data.
Arrays appear everywhere in PHP: decoded JSON, request data, configuration, database rows, form errors, route parameters, grouped records, and small scripts. A junior developer needs to do more than create an array. You need to read values safely, check whether keys exist, add and remove items, loop over records, transform values, and sort data without losing track of the keys.
Lists And Keyed Arrays
A list uses numeric keys. PHP assigns the keys automatically when you append values.
<?php
$tags = ['php', 'beginner'];
$tags[] = 'arrays';
print_r($tags);
// Prints:
// Array
// (
// [0] => php
// [1] => beginner
// [2] => arrays
// )
A keyed array uses meaningful keys.
<?php
$product = [
'sku' => 'BOOK-001',
'name' => 'PHP Workbook',
'price_cents' => 2499,
'in_stock' => true,
];
echo $product['name'] . " costs {$product['price_cents']} cents\n";
// Prints:
// PHP Workbook costs 2499 cents
Use keyed arrays when each value has a name. Use lists when order matters and each item has the same meaning.
Reading Optional Keys
Reading a missing key causes a warning. Decide what should happen when a key is missing.
<?php
$product = [
'name' => 'PHP Workbook',
'price_cents' => 2499,
];
$currency = $product['currency'] ?? 'GBP';
echo $currency . "\n";
// Prints:
// GBP
Use ?? when a simple fallback is correct. Use array_key_exists() when you need to distinguish "the key is missing" from "the key exists but contains null".
<?php
$product = ['discount_cents' => null];
var_dump(array_key_exists('discount_cents', $product));
var_dump(isset($product['discount_cents']));
// Prints:
// bool(true)
// bool(false)
isset() is false for null. array_key_exists() only asks whether the key exists.
Nested Arrays
Nested arrays let you represent records inside records.
<?php
$order = [
'id' => 1001,
'customer' => [
'name' => 'Amo',
'email' => 'amo@example.com',
],
'items' => [
['sku' => 'BOOK-001', 'quantity' => 2],
['sku' => 'PEN-002', 'quantity' => 1],
],
];
echo $order['customer']['email'] . "\n";
echo $order['items'][0]['sku'] . "\n";
// Prints:
// amo@example.com
// BOOK-001
Nested arrays are common after decoding JSON or fetching rows grouped by another value. The risk is assuming every nested key exists. Check at the boundary before relying on external data.
Adding, Updating, Removing, And Reindexing
Arrays are often changed in small steps.
<?php
$tags = ['php', 'arrays'];
$tags[] = 'practice';
$tags[1] = 'array-basics';
unset($tags[0]);
print_r($tags);
print_r(array_values($tags));
// Prints:
// Array
// (
// [1] => array-basics
// [2] => practice
// )
// Array
// (
// [0] => array-basics
// [1] => practice
// )
unset() removes an item but does not renumber numeric keys. Use array_values() when you need a clean zero-based list afterward.
Checking Membership And Searching
Use in_array() to check whether a value appears in an array. Pass true as the third argument for strict comparison.
<?php
$allowedStatuses = ['pending', 'paid', 'failed'];
var_dump(in_array('paid', $allowedStatuses, true));
var_dump(in_array('0', [0, 1, 2], true));
// Prints:
// bool(true)
// bool(false)
Use array_search() when you need the key where a value was found.
<?php
$statuses = ['pending', 'paid', 'failed'];
$position = array_search('paid', $statuses, true);
var_dump($position);
// Prints:
// int(1)
Be careful: array_search() can return 0, which is a valid key but falsey. Compare the result with !== false.
Filtering, Mapping, And Walking
array_filter() keeps items that pass a check.
<?php
$products = [
['name' => 'Notebook', 'in_stock' => true],
['name' => 'Pen', 'in_stock' => false],
['name' => 'Mug', 'in_stock' => true],
];
$inStock = array_filter($products, fn (array $product): bool => $product['in_stock']);
print_r(array_column($inStock, 'name'));
// Prints:
// Array
// (
// [0] => Notebook
// [2] => Mug
// )
array_filter() preserves keys. Use array_values() afterward if you need a reindexed list.
array_map() transforms each item and returns a new array.
<?php
$prices = [1299, 2500, 999];
$labels = array_map(
fn (int $cents): string => '£' . number_format($cents / 100, 2),
$prices
);
print_r($labels);
// Prints:
// Array
// (
// [0] => £12.99
// [1] => £25.00
// [2] => £9.99
// )
array_walk() is useful when you want to visit each item, often to modify values by reference.
<?php
$names = [' ada ', ' grace '];
array_walk($names, function (string &$name): void {
$name = trim($name);
});
print_r($names);
// Prints:
// Array
// (
// [0] => ada
// [1] => grace
// )
Use by-reference callbacks carefully. If returning a new array is clearer, prefer array_map().
Pulling Columns And Indexing Records
array_column() pulls one key from each nested array.
<?php
$products = [
['sku' => 'BOOK-001', 'name' => 'PHP Workbook'],
['sku' => 'PEN-002', 'name' => 'Pen'],
];
$namesBySku = array_column($products, 'name', 'sku');
print_r($namesBySku);
// Prints:
// Array
// (
// [BOOK-001] => PHP Workbook
// [PEN-002] => Pen
// )
This pattern is common when you need fast lookup by ID, SKU, email, or another unique value.
Sorting
Use sort() for simple lists when you do not care about preserving keys. Use asort() when keys matter. Use usort() for custom comparison logic.
<?php
$products = [
['name' => 'Notebook', 'price_cents' => 1299],
['name' => 'Mug', 'price_cents' => 899],
['name' => 'Backpack', 'price_cents' => 4200],
];
usort($products, fn (array $a, array $b): int => $a['price_cents'] <=> $b['price_cents']);
print_r(array_column($products, 'name'));
// Prints:
// Array
// (
// [0] => Mug
// [1] => Notebook
// [2] => Backpack
// )
The spaceship operator <=> returns the comparison result that usort() expects.
Merging Settings
Arrays are often used for configuration. Later values can override defaults.
<?php
$defaults = [
'currency' => 'GBP',
'items_per_page' => 20,
];
$userSettings = [
'items_per_page' => 50,
];
$settings = array_merge($defaults, $userSettings);
print_r($settings);
// Prints:
// Array
// (
// [currency] => GBP
// [items_per_page] => 50
// )
For string keys, array_merge() lets later arrays override earlier arrays. Numeric keys behave differently because lists are reindexed.
Common Mistakes
Do not assume a key exists just because one example has it. External data can be missing, null, duplicated, wrongly typed, or shaped differently.
Do not use loose membership checks for security or status decisions. Use strict comparison with in_array() and array_search().
Do not forget that some array functions preserve keys and others reindex. If JSON output needs a list, reindex with array_values() after filtering.
What You Should Be Able To Do
After this lesson, you should be able to:
- create lists, keyed arrays, and nested arrays;
- read required and optional keys deliberately;
- add, update, remove, and reindex values;
- check membership and search by value;
- filter, map, and walk arrays;
- pull columns and build lookup arrays;
- sort records by a field;
- merge default settings with overrides.
Practice
Task: Product Summary
Task
Create a $product keyed array with sku, name, price_cents, and in_stock.
Print a summary in this format:
BOOK-001: PHP Workbook costs 2499 cents
Then read an optional currency key with a default of GBP and print it.
Show solution
Solution
<?php
$product = [
'sku' => 'BOOK-001',
'name' => 'PHP Workbook',
'price_cents' => 2499,
'in_stock' => true,
];
$currency = $product['currency'] ?? 'GBP';
echo "{$product['sku']}: {$product['name']} costs {$product['price_cents']} cents\n";
echo "Currency: {$currency}\n";
// Prints:
// BOOK-001: PHP Workbook costs 2499 cents
// Currency: GBP
Explanation
The required fields are read directly. The optional currency field uses ?? because a simple fallback is correct for this exercise.
Task: Predict Array Keys
Task
Before running this code, predict both arrays printed by print_r().
<?php
$tags = ['php', 'arrays', 'practice'];
unset($tags[1]);
print_r($tags);
print_r(array_values($tags));
Then run the code and compare the output with your prediction.
Show solution
Solution
<?php
$tags = ['php', 'arrays', 'practice'];
unset($tags[1]);
print_r($tags);
print_r(array_values($tags));
// Prints:
// Array
// (
// [0] => php
// [2] => practice
// )
// Array
// (
// [0] => php
// [1] => practice
// )
Explanation
unset() removes the value but keeps the remaining numeric keys as they were. array_values() creates a new zero-based list.
Task: Build Order List
Task
Build an $order array with an id and an items list. Each item should have sku and quantity.
Loop over the items and print:
BOOK-001 x 2
PEN-002 x 1
Show solution
Solution
<?php
$order = [
'id' => 1001,
'items' => [
['sku' => 'BOOK-001', 'quantity' => 2],
['sku' => 'PEN-002', 'quantity' => 1],
],
];
foreach ($order['items'] as $item) {
echo "{$item['sku']} x {$item['quantity']}\n";
}
// Prints:
// BOOK-001 x 2
// PEN-002 x 1
Explanation
The order contains a nested list of items. foreach visits each item array and reads the sku and quantity keys.
Task: Sort And Index Products
Task
Given a list of products with sku, name, and price_cents:
- sort the products by price from low to high;
- print the sorted product names;
- build
$namesBySkuusingarray_column(); - print the lookup array.
Show solution
Solution
<?php
$products = [
['sku' => 'BOOK-001', 'name' => 'PHP Workbook', 'price_cents' => 2499],
['sku' => 'MUG-002', 'name' => 'Mug', 'price_cents' => 899],
['sku' => 'BAG-003', 'name' => 'Backpack', 'price_cents' => 4200],
];
usort($products, fn (array $a, array $b): int => $a['price_cents'] <=> $b['price_cents']);
print_r(array_column($products, 'name'));
$namesBySku = array_column($products, 'name', 'sku');
print_r($namesBySku);
// Prints:
// Array
// (
// [0] => Mug
// [1] => PHP Workbook
// [2] => Backpack
// )
// Array
// (
// [MUG-002] => Mug
// [BOOK-001] => PHP Workbook
// [BAG-003] => Backpack
// )
Explanation
usort() changes the order of the product records. array_column($products, 'name', 'sku') builds a lookup where each SKU points to the product name.
Task: Merge And Print Settings
Task
Merge default settings with user settings.
Defaults:
currencyisGBP;items_per_pageis20;show_taxistrue.
User settings:
items_per_pageis50.
Print the merged settings.
Show solution
Solution
<?php
$defaults = [
'currency' => 'GBP',
'items_per_page' => 20,
'show_tax' => true,
];
$userSettings = [
'items_per_page' => 50,
];
$settings = array_merge($defaults, $userSettings);
print_r($settings);
// Prints:
// Array
// (
// [currency] => GBP
// [items_per_page] => 50
// [show_tax] => 1
// )
Explanation
For string keys, later arrays override earlier arrays. The user setting replaces the default items_per_page, while the other defaults remain.