Search code examples
doctrine-ormembeddable

How to use Doctrine Embeddables


I'm trying to use Doctrine embeddables in a Symfony 2 project.

I have a class Purchase where I have a price field that is the embeddable:

/**
 * Products
 *
 * @ORM\Table(name="purchases")
 * @ORM\Entity
 */
class Purchase
{
    /**
     *
     * @ORM\Embedded(class="AppBundle\Entity\Embeddable\PriceEmbeddable")
     */
    private $price;

    /**
     * Set price
     *
     * @param MoneyInterface $price
     * @return $this
     */
    public function setPrice(MoneyInterface $price)
    {
        $this->price = $price;

        return $this;
    }

    /**
     * Get price
     *
     * @return MoneyInterface|float
     */
    public function getPrice()
    {
        return $this->price;
    }

}

As a price needs a currency to be complete, so I have the embeddable class that stores those two values:

/**
 * @ORM\Embeddable
 */
class PriceEmbeddable
{
    /** @ORM\Column(type = "integer") */
    private $amount;

    /** @ORM\Column(type = "string") */
    private $currency;
}

Now, the schema in the database is created correctly, but, when I persist the Purchase entity, I get the following error:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'price_amount' cannot be null

And I belive it: I'm yet not understanding how the mechanism works.

How I set and get values from the "real" entity (Purchase)?

I pass the value as a Money object (a value object I use) to the method setPrice() in the Purchaseentity, but, how this value is splitted into the two properties amount and currency and set in the embeddable class?

Because doing a var_dump (using the dump() function of VarDumper) I get the Entity set the right way:

PurchaseListener.php on line 58:
Purchase {#1795 ▼
  ...
  -price: Money {#1000 ▼
    -amount: 86
    -currency: Currency {#925 ▼
      -currencyCode: "EUR"
    }
  }
}

But those values are not set in the Embeddable and I don't understand why...

I've also tried to hard code the values in the embedded class, but anyway it doesn't work and, again, I don't understand why:

/**
 * @ORM\Embeddable
 */
class PriceEmbeddable
{
    /** @ORM\Column(type = "integer") */
    private $amount;

    /** @ORM\Column(type = "string") */
    private $currency;

    public function __construct($value)
    {
        $this->currency = 'EUR';
        $this->amount = 90;
    }

    public function setAmount($amount)
    {
        $this->amount = $amount = 90;
    }

    public function setCurrency($currency)
    {
        $this->currency = $currency = 'EUR';
    }

    public function getAmount()
    {
        return $this->amount;
    }

    public function getCurrency()
    {
        return $this->currency;
    }
}

Solution

  • This is the simple solution:

    /**
     * Products
     *
     * @ORM\Table(name="purchases")
     * @ORM\Entity
     */
    class Purchase
    {
        /**
         *
         * @ORM\Embedded(class="AppBundle\Entity\Embeddable\PriceEmbeddable")
         */
        private $price;
    
        /**
         * Set price
         *
         * @param PriceEmbeddable $price
         * @return $this
         */
        public function setPrice(PriceEmbeddable $price)
        {
            $this->price = $price;
    
            return $this;
        }
    
        /**
         * Get price
         *
         * @return PriceEmbeddable
         */
        public function getPrice()
        {
            return $this->price;
        }
    
    }