When empty is not empty
Recently when I was working on a project I got some strange results when using the empty
function. Here's what I was debugging. I've simplified the code a bit to share with you.
var_dump(
$person->firstName,
empty($person->firstName)
);
This was the result:
string(5) "Freek"
bool(true)
That's really odd. How can a variable hold a string and be empty at the same time? Let's try a few other functions on $person->firstName
:
var_dump(
$person->firstName,
empty($person->firstName),
isset($person->firstName),
is_null($person->firstName)
);
The result:
string(5) "Freek"
bool(true) // empty
bool(true) // isset
bool(false) // is_null
isset
and is_null
behave like expected, only empty
returns the wrong result.
Let's take a look at the implementation of the Person
class.
class Person
{
protected $attributes = [];
public function __construct(array $attributes)
{
$this->attributes = $attributes;
}
public function __get($name)
{
return $this->attributes[$name] ?? null;
}
}
Here you can see that the properties on a Person
object are retrieved from the $attributes
array using that magic __get()
method.
When passing variables to normal functions $person->firstName
will be evaluated first. The result of that evaluation will get passed to the function.
But empty
is not a function, it's a language construct. So what you pass to it will not be evaluated first. When passing $person->firstName
to it, it will check the contents of the firstName
property on $person
. Since that property doesn't exist, it will return false
.
If you want to make the empty
function work in this case you'll need to implement the magic __isset
method.
class Person
{
protected $attributes = [];
public function __construct(array $attributes)
{
$this->attributes = $attributes;
}
public function __get($name)
{
return $this->attributes[$name] ?? null;
}
public function __isset($name)
{
$attribute = $this->$name;
return !empty($attribute);
}
}
When empty
does it's job it'll use that magic method to determine the result.
Let's try dumping again:
var_dump(
$person->firstName,
empty($person->firstName)
);
The new results:
string(5) "Freek"
bool(false)
Perfect!
What are your thoughts on "When empty is not empty"?