tags:

views:

34

answers:

3

Hello !

Simple class for example:

class Foo
{
    protected $_bar;

    public function setBar( $value ) {

        $this->_bar = $value;

    }

}

And here is the question:

$obj = new Foo();

  var_dump( empty( $obj ) );  // true

$obj->setBar( 'foobar' );

  var_dump( empty( $obj ) );  // false

Is it possible to change class's behaviour with testing it with empty() function so it will returns true when object is not filled with data ?

I know about magic function __isset( $name ) but it is called only when we test specific field like:

empty( $obj->someField );

but not when test whole object.

A: 

PHP 5+ should treat objects with or without properties as non-empty all the time. I've just tested the above code on my PHP 5.3.2 server and var_dump returned FALSE on both occasions (which is correct). Which version of PHP are you using?

EDIT: PHP's "empty" behaviour can't be changed. You could use your own empty-checking function though. Try this:

function is_empty($object) {
    $object = (array)$object;
    foreach ($object as $key => $value) {
        if (!empty($value)) return FALSE;
    }
    return TRUE;
}

$obj = new Foo();   
var_dump(is_empty($obj)); // true
$obj->setBar('foobar');
var_dump(is_empty($obj)); // false
Wireblue
I know - I have the same results.. But I want change that behaviour - and about that is my question - is it possible ?
hsz
Sorry, I misread your question. See my edited response above.
Wireblue
+1  A: 

No, you can't change the behaviour of the empty function.

class Foo
{
    private $_empty = true;

    protected $_bar;

    public function setBar( $value ) {
        $this->_bar = $value;
        $this->_empty = false;
    }

    public function isEmpty() {
        return $this->_empty;
    }

}


$obj = new Foo();
    var_dump( $obj->isEmpty() );  // true

$obj->setBar( 'foobar' );
    var_dump( $obj->isEmpty() );  // false
Mark Baker
Code is obvious but thanks. :)
hsz
A: 

It kind of is possible. The opcode calls i_zend_is_true:

    if (!isset || !i_zend_is_true(*value)) {
        ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
    } else {
        ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
    }

which has this definition for objects (as of trunk):

    case IS_OBJECT:
        if(IS_ZEND_STD_OBJECT(*op)) {
            TSRMLS_FETCH();

            if (Z_OBJ_HT_P(op)->cast_object) {
                zval tmp;
                if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_BOOL TSRMLS_CC) == SUCCESS) {
                    result = Z_LVAL(tmp);
                    break;
                }
            } else if (Z_OBJ_HT_P(op)->get) {
                zval *tmp = Z_OBJ_HT_P(op)->get(op TSRMLS_CC);
                if(Z_TYPE_P(tmp) != IS_OBJECT) {
                    /* for safety - avoid loop */
                    convert_to_boolean(tmp);
                    result = Z_LVAL_P(tmp);
                    zval_ptr_dtor(&tmp);
                    break;
                }
            }
        }
        result = 1;
        break;

So if a cast to bool results in the value false (or if thee object is a proxy object and proxied value converts to false), empty will return true. However, to take advantage of this, you have to write a custom object in a PHP extension.

Artefacto