Force result for empty() test on an object
Simple class for example:
class Foo
{
protected $_bar;
pu开发者_C百科blic 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.
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
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.
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
精彩评论