11

When coding php I try to avoid as many warnings as possible. There is one question that bugs me for quite some time now, regarding arrays.

When working with arrays and their values I often check for empty values first before I go to the "real work".

if(array_key_exists('bla', $array){
  if( !empty($array['bla']) {
    # do something
  }
}

My Question is:

This is a lot of code for just checking if I have values to work with. Is there some shorter way to check a value within an array that may or may not exist?

Jan Turoň
  • 31,451
  • 23
  • 125
  • 169
Tom
  • 111
  • 1
  • 1
  • 3
  • Pretty sure all you need is the [empty](http://php.net/empty) clause which wont throw a warning: `Determine whether a variable is considered to be empty. A variable is considered empty if it does not exist or if its value equals FALSE. empty() does not generate a warning if the variable does not exist.` – Brock Hensley Dec 11 '13 at 22:40

5 Answers5

11

Don't use empty unless you are sure that's what you want:

Returns FALSE if var exists and has a non-empty, non-zero value. Otherwise returns TRUE.

The following things are considered to be empty:

  • "" (an empty string)
  • 0 (0 as an integer)
  • 0.0 (0 as a float)
  • "0" (0 as a string)
  • NULL
  • FALSE
  • array() (an empty array)
  • $var; (a variable declared, but without a value)

The manual doesn't explicitly list the "if var doesn't exist" cases, but here are a couple:

  • $array['undeclaredKey'] (an existing array, but key not declared)
  • $undeclaredVar; (a variable not declared)

Usually the array_key_exists check should suffice.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 1
    This bit me a few times when 0 was a legitimate value, like using a boolean to indicate state of an object being active or not. – Mike Purcell Dec 11 '13 at 23:10
  • Also returns true without a notice for an array key that isn't defined and for a variable that isn't defined, which is relevant to OP's question. – dualmon Dec 18 '15 at 17:40
  • 1
    @dualmon: The first line of the quote says that (if subtly). ;) The manual doesn't list them, though, true (it's obviously not intended to be an exhaustive list — only a demonstration of how variables that actually do exist can still result in `empty(x) == true`). I've adjusted your edit because it broke the correctness of the PHP manual quote. – Lightness Races in Orbit Dec 18 '15 at 18:36
6

If you are checking for a non-empty value, then you can just use !empty($array['bla']).

You can also use isset($array['bla']), which returns false when: 1) key is not defined OR 2) if the value stored for the key is null. The only foolproof way to check if the array contains a key (even if its value is null) is to use array_key_exists().

The call to empty() is safe even if the key exists (behaves like isset()), so you don't have to protect it by the array_key_exists().

I am surprised this was not mentioned, but the shortest way fetch a value for a key without generating a warning/error is using the Error Control Operator:

// safely fetch from array, will return NULL when key doesn't exist
$value = @$array['bla'];

This allows you get the value for any key with the possibilty of its return value being null if the key does not exist.

Phil M
  • 432
  • 7
  • 16
2

Just do:

if (!empty($array['bla'])) {

There will be no warning if the key doesn't exist.

webbiedave
  • 48,414
  • 8
  • 88
  • 101
  • ... or if the key does exist, but the value is falsey. That includes `"0"`. Sorry, but -1 from me: `empty` is very rarely fit for purpose. – Lightness Races in Orbit Dec 11 '13 at 22:47
  • @LightnessRacesinOrbit That wasn't the question. It's up to OP if `empty` meets his conditional requirement. In fact, he's already using it as such. – webbiedave Dec 11 '13 at 22:50
  • Doesn't mean he _should_ be, or that it does what he wants. `for just checking if I have values to work with` implies not. The string `"0"`, to most people, is a perfectly reasonable and _extant_ value, and certainly not a good criterion for suggesting that an array element with this value "doesn't exist" at all. – Lightness Races in Orbit Dec 11 '13 at 22:52
  • yeah, and trying to catch the "else" case doesn't bring any result, e.g. for producing error messages for the users... – Tom Dec 11 '13 at 22:54
  • @Tom: What do you mean "doesn't bring any result"? – Lightness Races in Orbit Dec 11 '13 at 22:55
  • @Lightness Races in Orbit: let's say I'd like to present an error message for an empty field, "if(!empty($array['bla'] ..." just ignores the else case, because 'bla' doesn't exist in $array at all. <-evil. – Tom Dec 11 '13 at 23:04
  • @Tom: I can't tell what you're talking about. Nothing "ignores the else case". If you construct your `if` statements to perform the logic you intend, then your program will behave as you intend... – Lightness Races in Orbit Dec 11 '13 at 23:15
  • @Tom: well you want to achieve two different goals with one ```if```. If you want to give different messages depending on the value then ```empty()``` is not the right choice and the initial code you were using is fine. – Kamafeather Sep 02 '15 at 13:59
2

You can simply do

if (!empty($array['bla']) {
 # do something
}

I use that all the time in drupal and is good way to check if is available and avoid any kind of warnings.

casivaagustin
  • 558
  • 5
  • 7
1

Not sure why no one mentioned isset yet, but you could do something like this:

// Before
if(array_key_exists('bla', $array){
    if( !empty($array['bla']) {

// After (if element of array is scalar)
//   Avoids warning and allows for values such as 0
if ((true === isset($array['bla'])) && (mb_strlen($array['bla']) > 0)) {

// After (if element of array is another array
//   Avoids warning and ensures element is populated
if ((true === isset($array['bla'])) && (count($array['bla']) > 0)) {

If you really want to get crazy with a better way of checking vars, you could create a standardized API, below are a few methods I created to avoid laundry list function calls for variable checking:

class MyString
{
    public static function populated($string)
    {
        //-----
        // Handle various datatypes
        //-----

        // Don't want to assume an array as a string, even if we serialize then check
        if (is_array($string)) {
            return false;
        }

        if (is_object($string)) {

            if (!is_callable(array($string, '__toString'))) {
                return false;
            }

            $string = (string) $string;
        }
        //-----

        return (mb_strlen($string) > 0) ? true : false;
    }
}

class MyArray
{
    public static function populatedKey($key, $array, $specificValue = null, $strict = true)
    {
        if ((is_array($array)) &&
            (array_key_exists($key, $array))) {

            if (is_array($array[$key])) {
                return (count($array[$key]) > 0) ? true : false;
            }

            elseif (is_object($array[$key])) {
                return true;
            }

            elseif (mb_strlen($array[$key]) > 0) {

                if (!is_null($specificValue)) {

                    if ($strict === true) {
                        return ($array[$key] === $specificValue) ? true : false;
                    } else {
                        return ($array[$key] == $specificValue) ? true : false;
                    }
                }

                return true;
            }
        }

        return false;
    }
}

// Now you can simplify calls

if (true === MyArray::populatedKey('bla', $array)) { // Do stuff }

if (true === MyString::populated($someString)) { // Do stuff }

There are 1K ways to skin a cat, but standardizing calls like this increase Rapid Application Development (RAD) quite a bit, keeps the calling code clean, and helps with self documentation (semantically logical).

Mike Purcell
  • 19,847
  • 10
  • 52
  • 89