Update Array Items
How Updating Works
In simple terms: To change a value in an array, assign a new value to its key: $product['price'] = 1199;. The old value is replaced.
Technically: Assigning to $array[$key] writes a value into the array's hash table. If the key exists, its value is replaced and its position is kept; if it does not exist, a new element is created at the end. Because arrays are values in PHP, updates affect only the variable being modified — not copies of the array held elsewhere.
Updating a Single Element
Example
<?php
$product = ['name' => 'Desk Lamp', 'price' => 1299, 'stock' => 10];
$product['price'] = 1199; // replace a value
$product['stock'] -= 2; // update based on the current value
$product['name'] .= ' (LED)'; // append to a string value
print_r($product);
Output
Array
(
[name] => Desk Lamp (LED)
[price] => 1199
[stock] => 8
)
How It Works
= 1199replaces the price.-= 2reads the current stock, subtracts 2, and writes the result back. All compound assignment operators (+=,-=,*=,.=,??=) work on array elements (see Assignment Operators).- The keys keep their original positions; updating never moves an element.
Indexed Arrays
<?php
$tasks = ['Write outline', 'Record video', 'Publish'];
$tasks[1] = 'Record and edit video';
print_r($tasks);
Output
Array
(
[0] => Write outline
[1] => Record and edit video
[2] => Publish
)
Update vs Accidental Creation
Assignment does not check whether a key exists. A typo silently creates a new key instead of updating the intended one:
<?php
$product = ['name' => 'Desk Lamp', 'price' => 1299];
$product['prise'] = 999; // typo
print_r($product);
Output
Array
(
[name] => Desk Lamp
[price] => 1299
[prise] => 999
)
The price is unchanged, and an extra key appears. When only existing keys should be changed, check first:
<?php
function updateExisting(array $data, string $key, mixed $value): array
{
if (!array_key_exists($key, $data)) {
throw new InvalidArgumentException("Unknown field: $key");
}
$data[$key] = $value;
return $data;
}
$product = ['name' => 'Desk Lamp', 'price' => 1299];
$product = updateExisting($product, 'price', 999);
echo $product['price'] . "\n";
try {
updateExisting($product, 'prise', 999);
} catch (InvalidArgumentException $e) {
echo $e->getMessage() . "\n";
}
Output
999
Unknown field: prise
For data with a fixed structure used throughout an application, classes with typed properties prevent this problem at the language level (see PHP Classes and Objects).
Updating Nested Arrays
Use one pair of brackets per level:
<?php
$order = [
'id' => 501,
'customer' => ['name' => 'Asha', 'address' => ['city' => 'Madurai']],
'items' => [
['name' => 'Gel Pen', 'qty' => 10],
['name' => 'Notebook', 'qty' => 3],
],
];
$order['customer']['address']['city'] = 'Chennai';
$order['items'][1]['qty'] += 2;
$order['customer']['address']['pin'] = '600042'; // creates a new nested key
echo $order['customer']['address']['city'] . " " . $order['customer']['address']['pin'] . "\n";
echo $order['items'][1]['name'] . ": " . $order['items'][1]['qty'] . "\n";
Output
Chennai 600042
Notebook: 5
Nested assignment also creates missing intermediate levels: $config['mail']['smtp']['port'] = 587; creates the mail and smtp arrays automatically if they do not exist.
Updating Every Element
Option 1: foreach With the Key
<?php
$prices = ['Pen' => 20, 'Notebook' => 60, 'Bag' => 1299];
foreach ($prices as $item => $price) {
$prices[$item] = round($price * 1.10, 2);
}
print_r($prices);
Output
Array
(
[Pen] => 22
[Notebook] => 66
[Bag] => 1428.9
)
Writing back through $prices[$item] updates the original array. Assigning to $price alone would only change a temporary copy.
Option 2: foreach by Reference
<?php
$prices = ['Pen' => 20, 'Notebook' => 60, 'Bag' => 1299];
foreach ($prices as &$price) {
$price = round($price * 1.10, 2);
}
unset($price);
echo implode(', ', $prices) . "\n";
Output
22, 66, 1428.9
&$price makes the loop variable an alias of each element. The unset($price) afterwards is essential to avoid the reference bug described in Foreach Loop.
Option 3: array_map() — Create an Updated Copy
<?php
$prices = ['Pen' => 20, 'Notebook' => 60, 'Bag' => 1299];
$newPrices = array_map(fn(float $price): float => round($price * 1.10, 2), $prices);
foreach ($newPrices as $item => $price) {
echo "$item: ₹" . number_format($price, 2) . "\n";
}
Output
Pen: ₹22.00
Notebook: ₹66.00
Bag: ₹1,428.90
array_map() returns a new array and leaves the original unchanged. With a single array argument, it preserves string keys. This is often the clearest option: the old and new prices both remain available, for example to show a "price changed" message.
Option 4: array_walk()
<?php
$prices = ['Pen' => 20, 'Notebook' => 60];
array_walk($prices, function (float &$price, string $item): void {
$price = round($price * 1.10, 2);
});
print_r($prices);
array_walk() calls a function for each element, passing the value (by reference, if declared with &) and the key. It modifies the array in place.
| Approach | Modifies Original? | Best For |
|---|---|---|
foreach with key | Yes | Clear, explicit updates |
foreach by reference | Yes | Short in-place updates (remember unset()) |
array_map() | No — returns a new array | Transformations, keeping the original |
array_walk() | Yes | Callback-based in-place updates |
Bulk Updates With array_replace()
<?php
$product = ['name' => 'Desk Lamp', 'price' => 1299, 'stock' => 10, 'active' => true];
$changes = ['price' => 999, 'stock' => 25];
$updated = array_replace($product, $changes);
print_r($updated);
Output
Array
(
[name] => Desk Lamp
[price] => 999
[stock] => 25
[active] => 1
)
array_replace() returns a new array in which values from the second array replace values with the same keys. Keys that exist only in $changes would be added, so filter incoming changes against allowed keys when they come from user input:
$allowed = ['price', 'stock'];
$safeChanges = array_intersect_key($changes, array_flip($allowed));
array_flip() turns the list of allowed names into keys, and array_intersect_key() keeps only matching keys. This prevents a request from changing fields such as id or is_admin.
Replacing a Range: array_splice()
<?php
$playlist = ['Intro', 'Song A', 'Song B', 'Outro'];
$removed = array_splice($playlist, 1, 2, ['Song X', 'Song Y', 'Song Z']);
echo implode(', ', $playlist) . "\n";
echo 'Replaced: ' . implode(', ', $removed) . "\n";
Output
Intro, Song X, Song Y, Song Z, Outro
Replaced: Song A, Song B
array_splice($array, $offset, $length, $replacement) removes $length elements starting at $offset, inserts the replacement elements, re-indexes the list, and returns the removed elements.
Updates Do Not Affect Copies
<?php
function applyDiscount(array $cart, int $percent): array
{
foreach ($cart as $sku => $price) {
$cart[$sku] = $price - $price * $percent / 100;
}
return $cart;
}
$cart = ['PEN-01' => 100, 'NB-A5' => 200];
$discounted = applyDiscount($cart, 10);
echo implode(', ', $cart) . "\n";
echo implode(', ', $discounted) . "\n";
Output
100, 200
90, 180
The function received a copy of $cart, updated it, and returned it. The caller's $cart is unchanged. This makes functions safe to call: they cannot modify your data unless you assign the result (or pass by reference deliberately).
Practical Example: Updating Inventory After an Order
<?php
function reserveStock(array $inventory, array $orderItems): array
{
$messages = [];
foreach ($orderItems as $sku => $quantity) {
if (!isset($inventory[$sku])) {
$messages[] = "$sku: unknown product";
continue;
}
$available = $inventory[$sku]['stock'];
if ($available < $quantity) {
$messages[] = "$sku: only $available in stock, requested $quantity";
continue;
}
$inventory[$sku]['stock'] -= $quantity;
$messages[] = "$sku: $quantity reserved, {$inventory[$sku]['stock']} left";
}
return [$inventory, $messages];
}
$inventory = [
'PEN-01' => ['name' => 'Gel Pen', 'stock' => 120],
'NB-A5' => ['name' => 'Notebook', 'stock' => 8],
'BAG-02' => ['name' => 'Backpack', 'stock' => 2],
];
$orderItems = ['NB-A5' => 3, 'BAG-02' => 5, 'PEN-01' => 20, 'MUG-01' => 1];
[$inventory, $messages] = reserveStock($inventory, $orderItems);
echo implode("\n", $messages) . "\n\n";
foreach ($inventory as $item) {
echo "{$item['name']}: {$item['stock']}\n";
}
Output
NB-A5: 3 reserved, 5 left
BAG-02: only 2 in stock, requested 5
PEN-01: 20 reserved, 100 left
MUG-01: unknown product
Gel Pen: 100
Notebook: 5
Backpack: 2
Step-by-Step Explanation
- The function receives copies of both arrays, so the caller's inventory changes only when the returned array is assigned.
- Unknown products and insufficient stock are reported and skipped with
continue. $inventory[$sku]['stock'] -= $quantityupdates one nested value in place.- The function returns two values — the updated inventory and the messages — as an array that is destructured by the caller.
In a real application, stock updates happen in the database inside a transaction, so that two customers cannot reserve the same last item at the same time (see MySQL Transactions with PHP).
Common Mistakes
Modifying the Loop Variable Instead of the Array
Effect: foreach ($items as $item) { $item['qty'] = 0; } changes nothing.
Fix: Write back with $items[$key], or loop by reference.
Typos Creating New Keys
Effect: The intended value is unchanged, and an extra key appears.
Fix: Validate keys before updating, or use classes for structured data.
Expecting a Function to Update the Caller's Array
Effect: Changes are lost because the function worked on a copy.
Fix: Return the updated array and assign it, or use pass by reference deliberately.
Applying Unfiltered User Changes
Effect: Requests can modify fields that should be protected.
Fix: Filter with array_intersect_key() against an allow-list.
Best Practices
- Update single values with direct assignment or compound operators.
- Prefer returning updated copies (
array_map(), functions that return arrays) for clarity. - When modifying in place in a loop, write back by key, or use references and
unset()afterwards. - Validate keys and filter incoming changes against an allow-list.
- Keep updates to shared data (inventory, balances) in the database inside transactions.
Official reference: https://www.php.net/manual/en/language.types.array.php#language.types.array.syntax.modifying