PHP: How do you delete an array element by its value?

unset($array[$key]) assumes you know the key. Often you only know the value, though. Then you have to look up the key first — and there is one line in that which is easy to get wrong.

Removing one occurrence

<?php
  $key = array_search('green', $colours, true);
  if ($key !== false) {
    unset($colours[$key]);
  }
?>

array_search() returns the key of the first match, or false if the value does not occur.

As described in article 0005, unset() leaves a gap in the keys:

array_search('green', $a, true) : 1
afterwards : ["red","blue"]  keys=[0,2]

If you need consecutive keys — because the array is meant to go out as a JSON array, for instance — append an array_values().

The line people get wrong

The !== false is not decoration. If you write plain if ($key) instead, the code works for every element except the first:

index of 'red'      : 0
if ($i)             : false   <- the match is missed!
if ($i !== false)   : true

array_search() returns key 0 for the first element, and 0 is falsy. The element is found and still not deleted. It is a bug that tends to be missed in tests, because you rarely test with the first element.

Incidentally the same goes for associative arrays with a key like '0' — PHP turns that into an integer internally.

The third parameter

The third parameter of array_search() switches to strict comparison. Without it PHP compares loosely, and then the search finds things you did not mean:

array_search('1', [1,2,3])        : 0       <- the string matches the integer
array_search('1', [1,2,3], true)  : false
array_search(0, [null,'x'])       : 0       <- null == 0
array_search(0, [null,'x'], true) : false

The second case is the nasty one. You search for the number 0 and delete a null. With data from a database, where null occurs regularly, that is a bug which stays unnoticed for a long time.

My recommendation: always set the third parameter to true. If you genuinely want a loose comparison, write a comment about it.

Removing all occurrences

array_search() only finds the first match. If the value occurs several times, you need something else.

array_filter() with a condition of your own:

<?php
  $withoutA = array_filter($values, fn($v) => $v !== 'a');
?>
array_filter : ["b","c"]  keys=[1,3]

array_diff() is shorter and can take several values at once:

<?php
  $withoutA  = array_diff($values, ['a']);
  $withoutAC = array_diff($values, ['a', 'c']);
?>
array_diff($e, ['a'])   : ["b","c"]  keys=[1,3]
several at once         : ["b"]

Both preserve the keys, so both leave gaps.

Why I do not recommend array_diff() everywhere

array_diff() has one property you need to know about: it compares the values as strings. The manual says so too, it is just that people rarely look it up.

array_diff([0,1,2,'0'], [false]) : [0,1,2,"0"]   <- nothing removed
array_diff([0,1,2], ['0'])       : [1,2]         <- the 0 is gone

In the first line false becomes '', and that is none of the elements — so nothing happens. In the second line '0' becomes '0' and thereby matches the integer 0.

So as soon as null, false or mixed types are in the array, array_diff() is the wrong choice. array_filter() with !== compares strictly and does exactly what it says. With pure string arrays — tags, names, IDs as text — you can use array_diff() without hesitation.

Associative arrays

With an associative array you specifically do not want array_values(), because it destroys your keys:

<?php
  $withoutOne = array_filter($config, fn($v) => $v !== 1);
?>
array_filter : {"b":2}

The keys are preserved, and here that is exactly right.

Summary

  • One occurrence: array_search() + unset(), checked with !== false.
  • The !== false is mandatory, otherwise the code fails on the first element.
  • Set the third parameter of array_search() to true — otherwise a search for 0 also matches a null.
  • All occurrences: array_filter() with !==, or array_diff().
  • array_diff() compares as strings; with null, false or mixed types prefer array_filter().
  • array_values() only for lists, not for associative arrays.

About Netcup (advertisement)

The German host Netcup offers, among other things, affordable and powerful web hosting packages, KVM-based root servers and dedicated servers. With our voucher codes you can save even more (6€ off your first order, 30% off all KVM-based root servers, ...).