Vitalie Ciubotaru
Vitalie Ciubotaru

Reputation: 75

isset and != in the same if clause

In my script a particular array element (say, $foo['bar']) can take different values, or no value at all. A particular action is triggered if the value of $foo['bar'] is not equal to, say, 42. The following code

if (!isset($foo['bar']) || ($foo['bar'] != '42')) action()

is not ideal, because php issues a warning about when $foo['bar'] is not set.

Question: is there an elegant way to test for such condition?

Upvotes: 1

Views: 158

Answers (4)

Emilio Gort
Emilio Gort

Reputation: 3470

Can be in this way

$bar = isset($foo['bar']) ? $foo['bar'] : NULL;

There you don't get warning and you are setting the variable.

Then you do the check

 if($bar != 42 && !empty($bar)){
    //do something
 }

Read Ternary Operator

The expression (expr1) ? (expr2) : (expr3) evaluates to expr2 if expr1 evaluates to TRUE, and expr3 if expr1 evaluates to FALSE.

Upvotes: 2

Alexander Yancharuk
Alexander Yancharuk

Reputation: 14501

For PHP 5.3+ you can use optimitzed version of Emilio Gort answer:

$bar = isset($foo['bar']) ?: '';
if ($bar != 42) action();

Upvotes: 1

Shakil Ahamed
Shakil Ahamed

Reputation: 577

I think this is what you want:

if (!(isset($foo['bar']) && ($foo['bar'] = '42'))) action();

Upvotes: 1

Ja͢ck
Ja͢ck

Reputation: 173562

This code:

if (!isset($foo['bar']) || $foo['bar'] != 42) {
}

Because of short-circuiting logic will actually not issue any warnings, because it skips at the first truthy condition, in this case that happens if $foo['bar'] is not defined.

This can also be seen from the opcodes that the compiler generates for your code:

compiled vars:  !0 = $foo
line  # *  op                           fetch          ext  return  operands
------------------------------------------------------------------------------
   3  0  >   ZEND_ISSET_ISEMPTY_DIM_OBJ                    1  ~0      !0, 'bar'
      1      BOOL_NOT                                         ~1      ~0
      2    > JMPNZ_EX                                         ~1      ~1, ->6
      3  >   FETCH_DIM_R                                      $2      !0, 'bar'
      4      IS_NOT_EQUAL                                     ~3      $2, 42
      5      BOOL                                             ~1      ~3
      6  > > JMPZ                                                     ~1, ->8
   4  7  > > JMP                                                      ->8
      8  > > RETURN                                                   1

The below opcode is important:

2    > JMPNZ_EX                                         ~1      ~1, ->6

The inverted outcome of isset($foo['bar']) gets checked and if truthy the code jumps over the next few statements that actually inspect the value of $foo['bar'], thereby avoiding any notices.

This also means that if you would reverse the two operands of || you will get a notice and the second operand is mostly useless anyway.

Because values like 0, false, [], etc. are also not equal to 42 you can use empty() as well:

if (empty($foo['bar']) || $foo['bar'] != 42) {
}

This arguably makes the code easier to read.

Upvotes: 4

Related Questions