Remove Array Items
Removing elements from an array can mean several different things: deleting a specific key, taking the last or first element, cutting out a range, removing every occurrence of a value, or keeping only elements that pass a test. PHP has a dedicated tool for each, and they differ in one important way — whether the remaining keys are kept or re-numbered.
| Task | Function | Keys After Removal |
|---|---|---|
| Remove by key | unset($array[$key]) | Kept (gaps remain) |
| Remove a range by position | array_splice() | Re-numbered |
| Remove and return the last element | array_pop() | — |
| Remove and return the first element | array_shift() | Re-numbered (integer keys) |
| Remove all occurrences of values | array_diff() | Kept |
| Remove specific keys | array_diff_key() | Kept |
| Remove elements failing a condition | array_filter() | Kept |
| Remove duplicates | array_unique() | Kept (first occurrence) |
unset() — Remove by Key
Example
<?php
$colors = ['red', 'green', 'blue', 'yellow'];
unset($colors[1]);
print_r($colors);
echo count($colors) . " colors left\n";
Output
Array
(
[0] => red
[2] => blue
[3] => yellow
)
3 colors left
How It Works
unset()removes the element with key1from the array.- The remaining elements keep their original keys, so the list now has a gap (
0, 2, 3). unset()on a key that does not exist does nothing — no warning.
Removing Several Keys at Once
<?php
$user = ['id' => 7, 'name' => 'Asha', 'password' => 'secret', 'token' => 'abc123'];
unset($user['password'], $user['token']);
print_r($user);
Output
Array
(
[id] => 7
[name] => Asha
)
unset() accepts several arguments. For associative arrays, gaps are not a concern — keys are names, not positions.
Re-indexing After unset()
<?php
$colors = ['red', 'green', 'blue', 'yellow'];
unset($colors[1]);
$colors = array_values($colors);
print_r($colors);
Output
Array
(
[0] => red
[1] => blue
[2] => yellow
)
Re-index lists with array_values() when continuous indexes matter — for for loops, for json_encode() (which turns gapped lists into JSON objects), or for index-based access.
array_splice() — Remove by Position
<?php
$colors = ['red', 'green', 'blue', 'yellow'];
$removed = array_splice($colors, 1, 2);
echo 'Remaining: ' . implode(', ', $colors) . "\n";
echo 'Removed: ' . implode(', ', $removed) . "\n";
print_r($colors);
Output
Remaining: red, yellow
Removed: green, blue
Array
(
[0] => red
[1] => yellow
)
array_splice($array, $offset, $length):
- removes
$lengthelements starting at position$offset, - re-indexes the remaining list,
- returns the removed elements.
A negative offset counts from the end: array_splice($list, -1) removes the last element. Note that $offset is a position, not a key — for lists with gaps, position and key can differ.
array_pop() and array_shift() — Take From the Ends
<?php
$tasks = ['first', 'second', 'third'];
$last = array_pop($tasks);
$first = array_shift($tasks);
echo "Popped: $last\n";
echo "Shifted: $first\n";
print_r($tasks);
$empty = [];
var_dump(array_pop($empty));
Output
Popped: third
Shifted: first
Array
(
[0] => second
)
NULL
| Function | Removes | Returns | Typical Use |
|---|---|---|---|
array_pop() | Last element | The removed value | Stacks (last in, first out) |
array_shift() | First element | The removed value | Queues (first in, first out) |
Both return null for an empty array. array_shift() re-indexes integer keys, which makes it slower than array_pop() on very large arrays.
Removing by Value
The First Occurrence: array_search() + unset()
<?php
$cart = ['Pen', 'Notebook', 'Pen', 'Eraser'];
$position = array_search('Pen', $cart, true);
if ($position !== false) {
unset($cart[$position]);
}
echo implode(', ', $cart) . "\n";
Output
Notebook, Pen, Eraser
array_search() returns the key of the first match, or false. The strict !== false check is essential, because the first match here is at key 0.
All Occurrences: array_diff()
<?php
$tags = ['php', 'spam', 'mysql', 'spam'];
$clean = array_values(array_diff($tags, ['spam']));
print_r($clean);
Output
Array
(
[0] => php
[1] => mysql
)
array_diff($array, $valuesToRemove) returns the elements of the first array whose values do not appear in the second. It keeps the original keys, so array_values() re-indexes the result. array_diff() compares values as strings ((string) $a === (string) $b).
Removing Specific Keys: array_diff_key()
To remove a list of keys — for example, sensitive fields before sending data to a browser:
<?php
$user = [
'id' => 7,
'name' => 'Asha',
'password_hash' => '$2y$10$abcdefghijklmnopqrstuv',
'api_token' => 'abc123',
];
$sensitive = ['password_hash', 'api_token'];
$publicUser = array_diff_key($user, array_flip($sensitive));
echo json_encode($publicUser) . "\n";
Output
{"id":7,"name":"Asha"}
array_flip()turns the list of field names into keys:['password_hash' => 0, 'api_token' => 1].array_diff_key()keeps only keys of$userthat are not in that list.- The original
$useris unchanged.
The opposite — keeping only listed keys — is array_intersect_key($user, array_flip(['id', 'name'])). An allow-list ("keep only these") is safer than a block-list ("remove these"), because new sensitive fields added later are excluded automatically.
Removing by Condition: array_filter()
array_filter() keeps elements for which a callback returns true, removing the rest:
<?php
$stock = ['Pen' => 10, 'Lamp' => 0, 'Bag' => 3, 'Mug' => 0];
$inStock = array_filter($stock, fn(int $quantity): bool => $quantity > 0);
print_r($inStock);
Output
Array
(
[Pen] => 10
[Bag] => 3
)
The Default Filter Trap
Without a callback, array_filter() removes every falsy value — including '0' and 0:
<?php
$answers = ['Asha', '', 'Bala', null, '0'];
var_export(array_values(array_filter($answers)));
echo "\n";
var_export(array_values(array_filter($answers, fn($v) => $v !== '' && $v !== null)));
echo "\n";
Output
array (
0 => 'Asha',
1 => 'Bala',
)
array (
0 => 'Asha',
1 => 'Bala',
2 => '0',
)
The default version silently drops the valid answer '0'. Pass an explicit callback whenever 0 or '0' can be legitimate data.
Removing Duplicates: array_unique()
<?php
$ratings = [3, 1, 3, 2, 1];
print_r(array_unique($ratings));
print_r(array_values(array_unique($ratings)));
Output
Array
(
[0] => 3
[1] => 1
[3] => 2
)
Array
(
[0] => 3
[1] => 1
[2] => 2
)
array_unique() keeps the first occurrence of each value and preserves its key. Re-index with array_values() for a clean list.
Removing Elements While Looping
Calling unset() on the array inside a foreach loop is safe — foreach iterates over the original list of elements:
<?php
$stock = ['Pen' => 10, 'Lamp' => 0, 'Bag' => 3, 'Mug' => 0];
foreach ($stock as $item => $quantity) {
if ($quantity === 0) {
unset($stock[$item]);
}
}
echo implode(', ', array_keys($stock)) . "\n";
Output
Pen, Bag
array_filter() expresses the same thing more directly when you only need the remaining items.
Removing Everything
$cart = []; // the variable still exists, as an empty array
unset($cart); // the variable itself no longer exists
Use $cart = []; to empty an array you will keep using. Use unset($cart) only when the variable is no longer needed.
Practical Example: Removing Expired Coupons
<?php
$coupons = [
'WELCOME10' => '2026-12-31',
'DIWALI25' => '2026-10-20',
'SUMMER15' => '2026-06-30',
'FLASH50' => '2026-10-08',
];
$today = '2026-10-09';
$active = array_filter($coupons, fn(string $expiry): bool => $expiry >= $today);
$expired = array_diff_key($coupons, $active);
echo "Active:\n";
foreach ($active as $code => $expiry) {
echo " $code (valid until $expiry)\n";
}
echo "Removed: " . implode(', ', array_keys($expired)) . "\n";
Output
Active:
WELCOME10 (valid until 2026-12-31)
DIWALI25 (valid until 2026-10-20)
Removed: SUMMER15, FLASH50
Step-by-Step Explanation
array_filter()keeps coupons whose expiry date is today or later. Dates inYYYY-MM-DDformat compare correctly as strings because they are ordered from the largest unit (year) to the smallest (day). For other formats, compareDateTimeImmutableobjects.array_diff_key()finds the coupons that were removed, by comparing keys of the original and the filtered array.- Both results keep the coupon codes as keys, so the codes can be listed with
array_keys().
In a real application, $today would be date('Y-m-d'), and expired coupons would usually be filtered in the database query (WHERE expires_on >= CURDATE()).
Common Mistakes
Expecting unset() to Re-index
Effect: Gaps break for loops and turn JSON arrays into objects.
Fix: Use array_values() afterwards, or array_splice().
Checking array_search() Loosely
Effect: A match at key 0 is treated as "not found".
Fix: if ($key !== false).
Default array_filter() Removing Valid Zeros
Effect: '0' and 0 disappear.
Fix: Always pass an explicit callback for user data.
Using array_splice() Offsets as Keys
Effect: In arrays with gaps or string keys, the wrong element is removed.
Fix: Use unset() for keys and array_splice() only for positions in lists.
Block-listing Sensitive Fields
Effect: New sensitive fields added later are exposed.
Fix: Allow-list public fields with array_intersect_key().
Best Practices
- Use
unset()to remove known keys, andarray_values()to re-index lists afterwards. - Use
array_splice(),array_pop(), andarray_shift()for position-based removal in lists. - Use
array_filter()with an explicit callback to remove by condition. - Use
array_diff()/array_diff_key()to remove values or keys in bulk without modifying the original. - Prefer allow-lists over block-lists when removing fields for security.
Official reference: https://www.php.net/manual/en/function.unset.php