php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75831 Coalesce operator ?? never uses the default isset() handler
Submitted: 2018-01-17 11:44 UTC Modified: 2019-01-25 16:24 UTC
Votes:2
Avg. Score:3.0 ± 2.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:1 (50.0%)
From: nobots dot nospam at example dot org Assigned: nikic (profile)
Status: Assigned Package: *General Issues
PHP Version: 7.2.1 OS:
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: nobots dot nospam at example dot org
New email:
PHP Version: OS:

 

 [2018-01-17 11:44 UTC] 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...


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-01-21 17:23 UTC] 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
 [2019-01-25 16:24 UTC] nikic@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: nikic
 [2019-01-25 16:24 UTC] 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
 [2020-04-23 09:21 UTC] michael dot vorisek at email dot cz
Is this expected to be fixed soon - and backported or at least in PHP 8.0?
 [2020-11-18 07:02 UTC] jakechapa at gmail dot com
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

```
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 16:01:29 2024 UTC