6

I know we can implement PHP's countable interface to determine how the function count() works as well as the Iterator interface for using an object like an array.

Is it possible to implement some kind of interface (or any other way) to change the behavior of empty() on an object?

Essentially, this is what I would like to be able to do:

<?php
class test {
    function __empty() {
        if (count($this->data) > 0) {
            return false;
        }
        return true;
    }
}

Just a nice to have!

Anderson Pimentel
  • 5,086
  • 2
  • 32
  • 54
teynon
  • 7,540
  • 10
  • 63
  • 106
  • 2
    *"change the behavior of empty()"* no, write your own function called MY_empty() - yes –  Jan 28 '13 at 18:50
  • I kind of figured there wasn't, but i'm not sure I understand why PHP wouldn't have implemented this. I'd think this would be a pretty simple implementation. All classes have __empty method, extended classes extend this. Especially since PHP revamped it so empty will always be false on an object. – teynon Jan 28 '13 at 18:54
  • well feel free to write your own version of php to do this :-) –  Jan 28 '13 at 18:55

4 Answers4

5

No there is not. The iterator behavior and count behaviors have no sense over an object; that's why you can override them. The default behavior of empty() applied to an object has a meaning instead: is it an instance of an object or is it NULL?; that's why you can't override it.

You can instead:

  • create a method inside the object called isEmpty() and implement it there
  • create a global function emptyObj() and implement it there
Shoe
  • 74,840
  • 36
  • 166
  • 272
  • You can also write you own function `is_empty()` implementing of what is empty or not in your eyes and then use that instead of PHP's version of `empty()`. – hakre Jan 28 '13 at 19:34
  • @hakre The problem is that you will receive warnings for the ones that aren't defined. – teynon Jan 28 '13 at 20:52
  • @Tom, you can always check if it's `isset` before checking it its empty. Also with the latter solution you can make it so it does not trigger warnings. – Shoe Jan 28 '13 at 20:53
  • @Jeffrey, one of the key points of empty is it checks isset. If I have to call isset then my own empty function... We are making it more difficult for ourselves. Calling isset inside of your user defined function is pointless. – teynon Jan 28 '13 at 20:55
  • @Tom, then why do you want to override it since `empty()` already does what you are asking for? – Shoe Jan 28 '13 at 20:59
  • @Jeffrey, the point is that all objects according to `empty()` are not empty. The point of the question is to extend `empty()` so that objects can be determined using a magic method or interface method. And if you mean to implement it like this: `function is_empty($var) { if (!isset($var)) return true; } if (is_empty($object)) echo "empty";` a warning will appear. – teynon Jan 28 '13 at 21:01
  • @Tom Well, either you are clearly not understanding what my idea is or I'm not understanding your problem; in both ways nobody cares if one understands the other since your problem was solved. Have a nice day. – Shoe Jan 28 '13 at 21:06
  • @Jeffrey, if you run the code I posted in the comment, you'll see that you get an undefined error. My goal is to call empty on any variable. If the variable is an object and has a method for example of `__empty`, it will request that method instead. – teynon Jan 28 '13 at 21:06
  • I would argue that the meaning you're attributing to `empty` actually is what's `isset` is for (or `is_null`). `empty` has additional/custom meaning depending on what type of variable it is applied to. So, if one is defining their own type, it would make perfect sense to be able to override `empty` as well. – Jānis Elmeris Oct 31 '19 at 10:07
4

No. PHP does not have it. You can request for such feature on wiki.php.net. In the meantime you can roll your own.

interface Empty_Checkable{
   function isempty();
}

class test implements Empty_Checkable{
    function isempty() {
        if (count($this->data) > 0) {
            return false;
        }
        return true;
    }
}
Shiplu Mokaddim
  • 56,364
  • 17
  • 141
  • 187
  • You need to have access on that page. Find someone who have access or raise the issue in #php-internal irc channel or mailing list. – Shiplu Mokaddim Jan 28 '13 at 19:31
  • By the way, proposing such a feature will likely be voted 'no' by the core devs. This is unfortunate as I have a library in-progress that would benefit from this extension. – Levi Morrison Jan 28 '13 at 19:47
3

This is not possible on the object directly.

If you need to do it, I would suggest implementing the Countable interface, and then instead of calling empty($foo), call count($foo) == 0...

However, for properties, it is possible using a combination of two magic methods: __isset and __get. For example:

class Foo {
    protected $bar = false;
    protected $baz = true;
    public function __get($key) {
        return $this->$key;
    }
    public function __isset($key) {
        return isset($this->$key);
    }
}

That results in:

empty($foo->abc); // true, isset returns false
empty($foo->bar); // true, isset returns true, but get returns false value
empty($foo->baz); // false, isset returns true, and get returns a true value

So no, it's not possible with a single method handler, but with the combination of the two magic methods, it works fine...

ircmaxell
  • 163,128
  • 34
  • 264
  • 314
  • This makes sense, but I'm not sure I see the point of implementing __get or __isset for properties since isset or empty works just fine without those methods. – teynon Jan 28 '13 at 20:09
1

It is possible to implement Countable

class MyCollection extends stdClass implements Serializable, ArrayAccess, Countable, Iterator, JsonSerializable
{
    public function count() {
        return count($this->array);
    }
}

and use !count() instead of empty() like

if (!count($myList)) {
    echo "List is empty!";
}
Fusca Software
  • 709
  • 6
  • 11