yiisoft/yii

isset(CMap) works wrong for null values

lmcsu opened this issue · 6 comments

lmcsu commented

What steps will reproduce the problem?

$map = new CMap();
$map['aaa'] = null;
var_dump(isset($map['aaa']));

What is the expected result?

false

What do you get instead?

true

Additional info

There must be checking for null.

public function offsetExists($offset)
{
    return $this->contains($offset);
}
Q A
Yii version 1.1.23
PHP version 7.4
Operating system any

I don't think this is a bug. Removing the items should be done using unset() call or remove() method.

A map can contain null values and the isset() call checks whether the key exists or not.

Here is an example of a SplOjectStorage map:

php -a
Interactive shell

php > $s = new SplObjectStorage();
php > $o = new stdClass();
php > $s[$o] = null;
php > var_dump(isset($s[$o]));
php shell code:1:
bool(true)

As you can see, setting the data to a null still reports that the key is there.

A map can contain null values and the isset() call checks whether the key exists or not.

isset() checks whether key exist and it is not null, you can use ArrayObject or simple array as an example: https://3v4l.org/UfXff

It's not a regression as this piece of CMap code hasn't changed in 10 years.

I don't think this is a bug. Removing the items should be done using unset() call or remove() method.

You are correct, this is the documented way to unset values, here: https://github.com/yiisoft/yii/blob/master/framework/collections/CMap.php#L20
And SplObjectStorage implements the isset check the same way.

isset() checks whether key exist and it is not null

You are also correct, you would expect this behavior regardless of how the value was "unset".

There is something to say for both argumentations, but for the sake of backwards compatibility, I would lean towards keeping this the way it is.

And SplObjectStorage implements the isset check the same way.

I don't think that SplObjectStorage should be used as an example here. It has many weird hacks and tricks and in many cases it behaves differently than regular array (which is the point of ArrayAccess).

@rob006 I agree from a design perspective, it makes sense for new developments. But for Yii 1 the behavior has always been like this (original map implementation from the Prado framework), and this behavior is sufficiently documented.