0

I started having a weird behavior with PHP's empty() function. Everything used to work properly, but now it doesn't, and I don't get why.

I have a tbInventory class that represents out products. One record per unit.

That class has a getBootloaderRevision method/property:

public function getBootloaderRevision() {
    if (empty($this->cBootloaderRevision)) {
        return null;
    } else {
        return $this->cBootloaderRevision;          
    }
}

It used to work, but now, the empty() function returns true even if the member has a value. Here is an example:

$prod = new tbInventory($db, 1009);
$test = $prod->cBootloaderRevision;
echo $prod->cBootloaderRevision . "<br>";
echo $test . "<br>";
echo (empty($prod->cBootloaderRevision) ? "1" : "02") . "<br>";
echo (empty($test) ? "1" : "0") . "<br>";

I'm loading an item from my database, an Item I know to have a BootLoader Revision. I declare and load it on the first line, then I put the value of the MEMBER itself straight in a variable. I then echo both the member and the variable to prove they both have the value.

I then echo a 1 or a 0 depending on the result of the empty() function for both the member and the variable. Here is the results:

01.07
01.07
1
0

I'm at a lost here. I do NOT understand why this is happening. I know it used to work, I haven't touched this in over a year. We made an update on the server recently, and it seems to have started acting this way since the server. I was not in charge of the update, but I think they updated both the OS and PHP.

Have you ever seen something like that???

Thank you,

Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141
Mathieu Turcotte
  • 344
  • 2
  • 14
  • 1
    `0` is not considered as being empty, nor is NULL if this is db related. – Funk Forty Niner Aug 09 '18 at 13:03
  • Are there any magic `__get`ters involved? – deceze Aug 09 '18 at 13:05
  • 5
    @Funk `empty(0)` and `empty(null)` are very much `true`…! – deceze Aug 09 '18 at 13:06
  • exactly what I was typing deceze – Rafael Aug 09 '18 at 13:06
  • @deceze oh yeah? *heh*, okie dokie then. – Funk Forty Niner Aug 09 '18 at 13:06
  • 1
    Is `__isset()` defined in the tbInventory class? – Elle H Aug 09 '18 at 13:06
  • Funk Forty Niner, please read again. The member contains "01.07". it doesn NOT contain just 0. Also, empty(0) is absolutely true... deceze, nope, no magical getter involved :( – Mathieu Turcotte Aug 09 '18 at 13:07
  • 1
    how many more guys are going to ping me here? **I GET IT.** *Jeez*. relax man. – Funk Forty Niner Aug 09 '18 at 13:08
  • 1
    There ist a pretty good explanation in php documentation (http://php.net/manual/en/function.empty.php) (see return values) or you can see some nice answers here: https://stackoverflow.com/a/15607549/3095216 – BenRoob Aug 09 '18 at 13:08
  • Dude... read the question... I have obviously read that page before. My value is "01.07". I'm trying to get why it returns true when it comes from the object's member, while it returns false when it comes from a variable... That page doesn NOT answer my question. – Mathieu Turcotte Aug 09 '18 at 13:13
  • is $test == $prod->cBootloaderRevision ?? – Salketer Aug 09 '18 at 13:19
  • please, can you show where cBootloaderRevision is declared/initialized? And if there is a __get function somewhere? – Salketer Aug 09 '18 at 13:20
  • 3
    If possible, reduce `tbInventory` to the bare minimum that shows this behavior and post that code; this is not reproducible as shown. – Tom Regner Aug 09 '18 at 13:20
  • One explanation for the behavior changing without changing the code, is a different behavior related to `offsetExists` introduced in PHP 7.0.5 (released 31.03.16; 2 and a half years ago). I put together a contrived example to illustrate the change. Of course I don't know if it is even related to your question. But here it is: https://3v4l.org/85uiY – jh1711 Aug 09 '18 at 14:45

1 Answers1

2

The only thing that would explain this behaviour is if cBootloaderRevision isn't a "physical" property but is being retrieved with the __get magic method, and the class either has no __isset method implemented or that method is returning results inconsistent with __get. The reason is that empty will invoke __isset first, but $prod->cBootloaderRevision will just invoke __get.

See http://php.net/manual/en/language.oop5.overloading.php#object.get.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • I'd have to analyse the DAL, I'm not the one who made it... It doesn't seem to use a magical getter, but these are also not actual members. They are added using a add() function defined in the TableObject class, which all the tables inherit from. The weird part is that this piece of code hasn't changed in at least a year and a half to two years. It always used to work.. until last week. I have fixed the issue by using a variable. These properties were badly coded anyway... now the property writes the "member" to a variable, and then I use a return empty($var) : null : $var; – Mathieu Turcotte Aug 09 '18 at 14:16
  • so the problem is fixed... but not explained XD. By chance, this is the only class in which I had properties doing this. I had two of them, and of course, both had the same issue. I guess I'll find out exactly what happened once I take an hour or two to analyse the DAL. Never really had time to look into it lol. Thanks for your help mate! – Mathieu Turcotte Aug 09 '18 at 14:17