php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #68654 empty function: late evaluation of argument
Submitted: 2014-12-25 21:59 UTC Modified: 2014-12-26 05:20 UTC
From: your dot brother dot t at hotmail dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.6.4 OS: Windows 8.1 64-bit
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: your dot brother dot t at hotmail dot com
New email:
PHP Version: OS:

 

 [2014-12-25 21:59 UTC] your dot brother dot t at hotmail dot com
Description:
------------
---
From manual page: http://www.php.net/function.empty
---
5.5.0	
empty() now supports expressions, rather than only variables.
---

The `empty()` can't evaluate multiple `__get()` results explicitly.

It seems that instead of correct nesting which is left to right nesting:
empty(...(((($this)->a)->b)->c)->...)
It uses a right to left nesting:
empty(($this->(a->(b->(c)->...)))...)
Which returns `null` at the first left-most `->` operator, yielding to an empty call to become true.

Test script:
---------------
<?php
class Juice extends Liquid{
   protected $apple;
   protected $orange;
   public function __get($name) {
      return $this->$name;
   }
   public function __construct($apple, $orange) {
      $this->apple = $apple;
      $this->orange = $orange;
   }
}

class Glass {
   protected $liquid;
   public function __get($name) {
      return $name == "liquid" ? $this->liquid : false;
   }
   public function __construct() {
      $this->juice = new Juice(3, 5);
   }
}

$glass = new Glass();
var_dump(empty($this->liquid));
var_dump(empty($this->liquid->apple));
var_dump(empty(($this->liquid->apple)));

?>

Expected result:
----------------
bool(false)
bool(false)
bool(false)

Actual result:
--------------
bool(false)
bool(true)
bool(false)

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-12-26 05:20 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2014-12-26 05:20 UTC] requinix@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

Your repro script is no good. I'm going to assume you meant more like
  http://3v4l.org/u1jQt

For isset() and empty() to work properly on objects that implement __get, __isset also needs to be implemented. Those functions will not try to access a value until they know it exists, and without __isset to tell them otherwise they will look for actual accessible properties.

> var_dump(empty($glass->liquid));
empty because ->liquid is not accessible.
> var_dump(empty($glass->liquid->apple));
empty because ->liquid is not accessible.
> var_dump(empty(($glass->liquid->apple)));
This one is a bit trickier to answer. Either it's empty because ->liquid is still not accessible, which is likely the logic used by HHVM and the last couple months' worth of PHP 7, or it is not empty because the extra parentheses forced evaluation and the subsequent value is not empty.

Regardless, you need to implement __isset. See
  http://3v4l.org/qaeJL
which gives the expected false/false/false.
You can put logging statements in __get and __isset to see exactly what is happening.
 
PHP Copyright © 2001-2026 The PHP Group
All rights reserved.
Last updated: Tue Oct 06 19:00:01 2026 UTC