mongodb-odm icon indicating copy to clipboard operation
mongodb-odm copied to clipboard

Type::convertToPHPValue is not called when $value is null

Open Bilge opened this issue 8 years ago • 12 comments

This seems to be incorrect behaviour considering types like Hash implement their own null checking. Furthermore it prevents marshalling nulls into empty collections. It should therefore be up to the implementation to decide how to handle null.

Bilge avatar Aug 05 '16 11:08 Bilge

I'll just note that this for work yet again requires passing mapping information to type as types may need to return different values when nullable is set to true

malarzm avatar Aug 05 '16 12:08 malarzm

It does not require passing mapping information. That should be regarded as an optional extra. It is not required in order to address this issue.

Bilge avatar Aug 05 '16 12:08 Bilge

So you're seeing this as something like this?

/** @ODM\Field(type="some-type", nullable=true, convertNull=true) */
private $someProp;

malarzm avatar Aug 05 '16 20:08 malarzm

I have never, in my life, used nor even heard of either nullable or convertNull. My annotation would simply be @ODM\Field(type="some-type").

Bilge avatar Aug 05 '16 20:08 Bilge

nullable allows field to be stored as null in database (otherwise it's $unset during an update effectively making field not present in the data passed to hydrator later). convertNull is new and is outcome of what I understood by "That should be regarded as an optional extra" as for the developer to opt in for.

malarzm avatar Aug 05 '16 21:08 malarzm

I think the problem, judging from the comments in the code you've linked, is that the logic assumes if you're not working with embed/reference one/many then you must be working with scalar data. My custom type marshals to and from a custom collection which is anything but scalar. It is initialized in the constructor to be a collection so if Doctrine tries to hydrate null it actually needs to become my custom collection instead, to be consistent. This it not possible if my type's conversion method is never called.

From reading the code it seems setting nullable to true would cause my type's conversion method to be called with the downside that it would start storing null instead of unsetting the field. I don't understand why these need to be mutually exclusive. I'd like to keep the behaviour of unsetting the field but still have my type's convertToPHPValue method called.

I do not know how convertNull works since there doesn't seem to be any reference to it in that code but perhaps this does what I want?

Bilge avatar Aug 05 '16 21:08 Bilge

But actually we never hydrate nulls (unless nullable=true is in place) so if you initialize the collection in ctor I'm not sure what is going wrong and when?

malarzm avatar Aug 05 '16 21:08 malarzm

The constructor is not called when the object is hydrated, therefore the field is null by default. That breaks any code that is expecting to work with the custom collection type unless null guards are spread throughout the code wherever the field is accessed, which would be a poor design.

Bilge avatar Aug 05 '16 21:08 Bilge

Ah right, sorry... I'll better go to sleep as I clearly am not capable of thinking anymore :baby:

malarzm avatar Aug 05 '16 21:08 malarzm

:baby_bottle:

Bilge avatar Aug 05 '16 21:08 Bilge

Updating this issue as I just bumped into the same problem: How to initialise a value to a default value as the constructor is not called nor the convertToPHPValue ?

MaxenceDupressoir avatar Jul 19 '21 14:07 MaxenceDupressoir

If the value is simple you can assign it directly to a property like private $something = false;. Otherwise, as we're still not passing null to the related Type object, you could utilize postLoad lifecycle event.

malarzm avatar Jul 19 '21 17:07 malarzm