1

I've got a Document class with an EmbeddedDocument multiple self-inherited. It's working fine, but when i'm not sending subData it's saved in Mongo as empty array (subData: []).

I would expect that this field isn't saved at all if not sent.

I've tried with nullable=false and nullable=true.

Not setting ArrayCollection in __construct makes error Call to a member function add() on null

  • Symfony 4.3
  • doctrine/mongodb 1.6.4
  • doctrine/mongodb-odm 1.3.7
  • doctrine/mongodb-odm-bundle 3.6.2
<?php

namespace App\Document;

use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

/**
 * @MongoDB\EmbeddedDocument()
 */
class Data
{
    /**
     * @MongoDB\Id()
     */
    private $id;

    /**
     * @MongoDB\Field(type="string")
     */
    private $value;

    /**
     * @MongoDB\EmbedMany(targetDocument="App\Document\Data", nullable=false)
     */
    public $subData = null;

    public function __construct()
    {
        $this->subData = new ArrayCollection();
    }

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

    public function getValue(): ?string
    {
        return $this->value;
    }

    public function setValue(string $value): self
    {
        $this->value = $value;

        return $this;
    }

    public function getSubData(): Collection
    {
        return $this->subData;
    }

    public function setSubData(array $subData): self
    {
        $this->subData = $subData;

        return $this;
    }

    public function addSubdata(Data $subData): self
    {
        $this->subData->add($subData);

        return $this;
    }
}

UPDATED

changing setter to this didn't help as suggest @Maniax it's still subData: []

    public function setSubData(array $subData): self
    {
        if(!empty($subData) && count($subData) > 0 && $subData !== null) {
            $this->subData = $subData;
        }

        return $this;
    }
  • 1
    Well you initialize it with an empty array, makes sense to return an empty array. You could check the value on the setter and not assign the value if it's empty. You could also change the addSubData method to initilize the array when adding the first element, so it's effectively null as long as you don't add an element. – Maniax Nov 04 '22 at 13:42

1 Answers1

1

If you don't want null in you database when the array is empty, you want to avoid initializing it by default, so avoid

public function __construct()
{
    $this->subData = new ArrayCollection();
}

The array still needs to be initialized, so in the add function you'll have to check if the array is not initialized before adding

public function addSubData(Data $subData): self
{
    // null and an empty array are falsey
    if (!$this->subData) {
        $this->subData = new ArrayCollection();
    }
    $this->subData->add($subData);
}

return $this;
}

And in the setter you check if you're not getting an empty array

public function setSubData(array $subData): self
{
    if(!empty($subData)) {
        $this->subData = $subData;
    }

    return $this;
}

This should prevent an empty array to end up in your database.

Maniax
  • 128
  • 1
  • 6