1

Sorry if it's an irritating question (i come from a ruby background and i am new to PHP).

I find it kind of weird that you can't do:

 if($defined_array['undefined_index'] == 'a string') {
     do_something();
 }

without getting slammed in the face with a warning.

  1. In this particular case, if the variable doesn't exist, how come you get a warning ? This is a weird implementation of equality for a loosely-typed language. It would make much more sense to only get a false. Is it due to interpreter limitations ? What are the technical reasons that are behind this ? I'm just curious.
  2. Is there any function, construct, idiom or whatever that i don't know that would avoid me to do this every 4 lines or so:

    if(isset($defined_array['undefined_index']) && $defined_array['undefined_index'] == 'a string') {
         do_something();
    }
    

    I know that i could declare every single array keys i intend to use, but what's the point of not being forced into declaring variables before using them if PHP intends to slap you every time you do it ?

m_x
  • 12,357
  • 7
  • 46
  • 60
  • 1
    Don't think so, but just as a side note, check out the array_key_exists() function as well. – ScoPi Nov 15 '12 at 08:44

6 Answers6

3

The reason for the warning is for code safety reasons. While it's possible that the reason the array key doesn't exist is because it's not supplied in this instance, it's also possible that there was a typo in either setting or retrieving the element. Without warnings, such coding errors would be harder to notice.

Barmar
  • 741,623
  • 53
  • 500
  • 612
2

No, not with the same expression. However, you could make an own comparison function or use the (ABSOLUTELY HORRIBLE) error suppression operator @. Error suppression is ALWAYS a bad idea though, I recommend you to solve the problem instead.

1: Own function:

function setAndEq($a, $b){
    if(isset($a, $b))
        return $a === $b;
    else
        return false;
}

if(setAndEq($array['undefined_index'], "hello")) {
    // hello
}

2: Error suppression:

if(@strcmp($array['undefined_index'], "hello") === 0) {

}
nyson
  • 1,055
  • 6
  • 20
1

It depends, first of all you can turn of your error_reporting, but i wouldn't reccomend you that.

When you have multiple checks for the same array-key you also could try this:

if (isset($defined_array['undefined_index'])) :
switch ($defined_array['undefined_index']) :
    case 'a string' :
        do_something();
    break;
    case 'b string' :
        do_anotherthing();
    break;    
endswitch;
endif;

In that case you don't have to worry about all the warnings on each row.

Ronn0
  • 2,249
  • 2
  • 21
  • 36
1

You could silence the warnings with setting an appropriate error level but that is not a really good idea. Personally i use a small function to ease on typing:

/**
 * nullsafe
 *
 * returns values from array like objects
 *
 * Usage:
 *    nullsafe($array, 'key'); - returns the $array['key'] if it is set
 *    nullsafe($array, 'key', 'foo'); - returns the $array['key'] if it is set, 'foo' otherwise
 *    nullsage($array, array('level0', 'level1')); returns $array['level0']['level1'] if it is set, null otherwise
 *
 * returns value indexed by $key from the $from, or the $default if its not present
 * if the key is an array then it will descend it into the $from like $from[$key[0]][$key[1]][$key[2]]...
 *
 * @param mixed $from
 * @param mixed $key
 * @param mixed $default
 * @return mixed
 */
function nullsafe($from, $key, $default = null) {
    if (!is_array($key)) {
        if (isset($from[$key])) {
            return $from[$key];
        }
    } else {
        foreach ($key as $k) {
            if (!isset($from[$k])) {
                return $default;
            } else {
                $from = $from[$k];
            }
        }
        return $from;
    }
    return $default;
}
complex857
  • 20,425
  • 6
  • 51
  • 54
  • +1, that's the approach i spontaneously have, but find it weird that it is not native. – m_x Nov 15 '12 at 09:05
  • Well undefined array keys do evaluate to `null`, also interestingly the `isset($stuff['foo']['bar'])` works as expected too – complex857 Nov 15 '12 at 09:07
  • yes, but you still get a warning when you test equality with an undefined array key... – m_x Nov 15 '12 at 09:10
  • oh sorry, i did not realize you were talking about your function. No idea on the technical reasons (question 1.) ? – m_x Nov 15 '12 at 09:11
  • 1
    I'm not sure of the reasons, but since php has only arrays as basic container data structures, it really useful when you use them as sets for example. – complex857 Nov 15 '12 at 10:56
1

Regarding 1: When a variable doesn't exist you should always get a warning. It indicates that you didn't write your code correct. When an unset variable (or an array key) would evaluate to FALSE, then this would be just wrong. I guess the question isn't what's the technical reason - it#s just common sense.

Regarding 2: No. Just use empty() or isset() and use strict type checking.. p.e. if ($x === FALSE) instead of if ($x == NULL).

Jan.
  • 1,925
  • 15
  • 17
  • it may be common sense in PHP, but as i said, i'm a noob (this is absolutely not common sense in ruby). I'm a bit offended by your tone. – m_x Nov 15 '12 at 10:05
  • Let me try to explain what I mean with common sense. Firstoff, I have no clue about ruby. Second: PHP wants to get away from oldschool style (if one can say so), where it was procedural and type converting all the time. Nowadays PHP brings your the possibility use strict type checking. so you can and (IMHO) should distinguish between a variables content.. false, null and '' does not equal `!isset()`. – Jan. Nov 15 '12 at 10:21
  • by the way. What I was trying to say was basically what you accepted as the answer. No offense intended. ;) Have a nice day… – Jan. Nov 15 '12 at 10:27
  • it' OK. I hear about strict type checking, i just did not understand this "arse-between-two-chairs" approach of letting you use undefined variables, but punishing you when you do so. I guess it has some historical reasons, as you highlighted... No offense taken, i'm just a bit grumpy because i'm out of coffee ;) – m_x Nov 15 '12 at 10:49
0

Edit: combining isset and the error control operator you may declare a function that always return the value of a variable or null if it is not set:

$ php -a
Interactive shell

php > function getvalue($var) {
php { return isset($var) ? $var: null;
php { }
php > $testarray['key1'] = "hello";
php > if ($myvar = @getvalue($testarray['key1'])) echo "var: " . $myvar;
var: hello
php > if ($myvar = @getvalue($testarray['key2'])) echo "var: " . $myvar;
php >

Note that you cannot distinguish between a variable that doesn't exist or a variable that does but its value is null.

etuardu
  • 5,066
  • 3
  • 46
  • 58
  • Sorry, I just misunderstood your question. I just edited the answer to provide a working solution. – etuardu Nov 15 '12 at 09:14