doctrine / mongodb-odm

The Official PHP MongoDB ORM/ODM
https://www.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/
MIT License
1.09k stars 501 forks source link

Nullable field can not be overwritten by null #2196

Open sFreezer opened 4 years ago

sFreezer commented 4 years ago

Bug Report

Q A
BC Break no
Version since 2.1.1

Summary

After this -> change

you can not overwrite any value on a nullable field to null with upsert. because it is just set on $setOnInsert and not on $set. I think: this was done to not overwrite a value by accident (by not calling the setter)

but we need to overwrite a value by setting it to null on purpose

Current behavior

class SomeDocument
{
    /**
     * @ODM\Id(strategy="NONE", type="integer")
     */
    private int $id;

    /**
     * @ODM\Field(type="integer", nullable=true)
     */
    private ?int $someNullabeInt = null;

    public function getId(): int
    {
        return $this->id;
    }

    public function setId(int $id): void
    {
        $this->id = $id;
    }

    public function getSomeNullabeInt(): ?int
    {
        return $this->someNullabeInt;
    }

    public function setSomeNullabeInt(?int $someNullabeInt): void
    {
        $this->someNullabeInt = $someNullabeInt;
    }
}
    public function test_Nullable(): void
    {
        $id = 1;

        $document = new SomeDocument();
        $document->setId($id);
        $document->setSomeNullabeInt(2);

        $this->documentManager->persist($document);
        $this->documentManager->flush();
        $this->documentManager->clear();

        $documentUpdate = new ProductMetricDocument();
        $documentUpdate->setId($id);
        $documentUpdate->setSomeNullabeInt(null);

        $this->documentManager->persist($documentUpdate);
        $this->documentManager->flush();
        $this->documentManager->clear();

        $repository = $this->documentManager->getRepository(SomeDocument::class);
        $fetchedDocumentAfterUpdate = $repository->find($id);
      }

$someNullabeInt will be 2 after running this code but it should be null

How to reproduce

by running the test from #Current behavior

Expected behavior

we need to be able to overwrite a value with null on purpose by calling the setter on null

malarzm commented 4 years ago

I'm afraid this is not going to happen unless we have explicit upsert support where we could give users control over setting null values (or not). Also changing the current behaviour would be a quite huge BC break given we introduced the change in 1.2 series.

sFreezer commented 4 years ago

As you can read in your docs

the nullable flag should do something else.

Option 1: this is a bug or Option 2: the docs are wrong

malarzm commented 4 years ago

The nullable flag description is correct, that's what is happening during insert and update, it is just upsert that works differently. If we don't have a section about upserting documents and its quirks, we shall write one.