Bug #75831 [Com]: Coalesce operator ?? never uses the default isset() handler

From: Date: Wed, 18 Nov 2020 07:02:23 +0000
Subject: Bug #75831 [Com]: Coalesce operator ?? never uses the default isset() handler
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-230419@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=75831&edit=1

 ID:                 75831
 Comment by:         jakechapa at gmail dot com
 Reported by:        nobots dot nospam at example dot org
 Summary:            Coalesce operator ?? never uses the default isset()
                     handler
 Status:             Assigned
 Type:               Bug
 Package:            *General Issues
 PHP Version:        7.2.1
 Assigned To:        nikic
 Block user comment: N
 Private report:     N

 New Comment:

I found the following behavior odd. Is it expected as ewll?

```
class MagicProp 
{
  public function __isset($key)
  {
	return false;
  }
  
  public function __get($prop) {
  	return 'yes';
  }
}   

$magic = new MagicProp();

return $magic->prop;       // returns 'yes'
return $magic->prop ?? 1;  // returns 1

```


Previous Comments:
------------------------------------------------------------------------
[2020-04-23 09:21:14] michael dot vorisek at email dot cz

Is this expected to be fixed soon - and backported or at least in PHP 8.0?

------------------------------------------------------------------------
[2019-01-25 16:24:46] nikic@php.net

I agree with the original reporter that this is a bug. $foo->bar ?? $baz should behave the same
way as isset($foo->bar) ? $foo->bar : $baz, and in this case it does not.

https://3v4l.org/UI13h

------------------------------------------------------------------------
[2018-01-21 17:23:41] timok at ya dot ru

Imho, this is not a bug, but quite expected and correct behavior.

You define a handler to get inaccessible properties (__get), then it is called whenever you try to
access an inaccessible property, including NULL coalesce operator. If object has a property check
method (__isset), then it is called before __get. So, the code

  var_dump($bar->foo ?? "qux"); // works now, without errors...

- is equivalent to the following:

  var_dump(isset($bar->foo) ? $bar->foo : "qux"); // also works without errors: https://3v4l.org/4EPXm

- http://php.net/manual/en/language.operators.comparison.php#language.operators.comparison.coalesce
- https://wiki.php.net/rfc/isset_ternary

------------------------------------------------------------------------
[2018-01-17 11:44:22] nobots dot nospam at example dot org

Description:
------------
The coalesce operator calls __get(prop) directly without testing isset($obj->prop) first.

It only calls isset($obj->prop) if there is an explicit user-defined __isset() handler.

Test script:
---------------
class Bar{
    function __get($a){
        throw new Error("no prop error\n");
    }
}

$bar = new Bar;

try{
    var_dump($bar->foo ?? "qux"); // error...
} catch(Throwable $e){ echo $e->getMessage(); }

var_dump(isset($bar->foo)); // ...but this works fine

Expected result:
----------------
class Bar{
    function __isset($a){
        return isset($this->{$a});
        // I shouldn't be forced to implement this,
        // since it looks exactly like the default isset() handler
    }
    function __get($a){
        throw new Error("no prop error\n");
    }
}

$bar = new Bar;
var_dump($bar->foo ?? "qux"); // works now, without errors...



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=75831&edit=1


Thread (5 messages)

« previous php.bugs (#230419) next »