Doctrine persist entity with inverse relation not work

493 Views Asked by At

I'm trying to save two entities linked. Product entity may have any or many entities ProviderRate. When I try to save the product entity, it tells me that ProviderRate related entity has not assigned one of their required fields. I need to save a product with no need to assign a ProviderRate.

The error message showing me is:

Entity of type AppBundle\Entity\ProviderRate is missing an assigned ID for field 'provider'.
The identifier generation strategy for this entity requires the ID field to be populated before EntityManager#persist() is called.
If you want automatically generated identifiers instead you need to adjust the metadata mapping accordingly.

My entitdades code is as follows:

Product Entity

 /**
    * Products
     *
         * @ORM\Table(name="products", uniqueConstraints={@ORM\UniqueConstraint(name="id_producto_UNIQUE", columns={"id"})}, indexes={@ORM\Index(name="fk_id_productos_id_categorias1_idx", columns={"category_id"}), @ORM\Index(name="fk_id_productos_id_producto_tipo1_idx", columns={"type"}), @ORM\Index(name="fk_id_productos_id_moneda1_idx", columns={"currency_id"})})
         * @ORM\Entity(repositoryClass="AppBundle\Repository\ProductsRepository")
         */
        class Products {
            /**
         * @var string
         *
         * @ORM\Column(name="name", type="string", length=45, nullable=false)
         * @Assert\NotBlank(message="Por favor, escriba el nombre del producto.")
         */
        private $name;

        /**
         * @var string
         *
         * @ORM\Column(name="description", type="string", length=255, nullable=false)
         */
        private $description;

        /**
         * @var string
         *
         * @ORM\Column(name="code", type="string", length=45, nullable=false)
         */
        private $code;

        /**
         * @var string
         *
         * @ORM\Column(name="description_long", type="text", nullable=false)
         */
        private $descriptionLong;

        /**
         * @var integer
         *
         * @ORM\Column(name="amount_per_unit", type="integer", nullable=false)
         */
        private $amountPerUnit;

        /**
         * @var string
         *
         * @ORM\Column(name="weight", type="decimal", precision=11, scale=3, nullable=false)
         */
        private $weight;

        /**
         * @var string
         *
         * @ORM\Column(name="web", type="string", length=100, nullable=false)
         */
        private $web;

        /**
         * @var boolean
         *
         * @ORM\Column(name="isActive", type="boolean", nullable=false)
         */
        private $isactive;

        /**
         * @var \DateTime
         *
         * @ORM\Column(name="createdtime", type="datetime", nullable=false)
         * @Assert\DateTime()
         */
        private $createdtime;

        /**
         * @var \DateTime
         *
         * @ORM\Column(name="modifiedtime", type="datetime", nullable=false)
         * @Assert\DateTime()
         */
        private $modifiedtime;

        /**
         * @var \DateTime
         *
         * @ORM\Column(name="deletedtime", type="datetime", nullable=true)
         */
        private $deletedtime;

        /**
         * @var boolean
         *
         * @ORM\Column(name="isDeleted", type="boolean", nullable=false)
         */
        private $isdeleted;

        /**
         * @var integer
         *
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="IDENTITY")
         */
        private $id;

        /**
         * @var \AppBundle\Entity\Categories
         *
         * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Categories")
         * @ORM\JoinColumns({
         *   @ORM\JoinColumn(name="category_id", referencedColumnName="id")
         * })
         */
        private $category;

        /**
         * @var \AppBundle\Entity\ProductTypes
         *
         * @ORM\ManyToOne(targetEntity="AppBundle\Entity\ProductTypes")
         * @ORM\JoinColumns({
         *   @ORM\JoinColumn(name="type", referencedColumnName="id")
         * })
         */
        private $type;

        /**
         * @var \AppBundle\Entity\Currencies
         *
         * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Currencies")
         * @ORM\JoinColumns({
         *   @ORM\JoinColumn(name="currency_id", referencedColumnName="id")
         * })
         */
        private $currency;

        /**
         * @var \Doctrine\Common\Collections\Collection
         *
         * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Sets", inversedBy="product")
         * @ORM\JoinTable(name="products_sets",
         *   joinColumns={
         *     @ORM\JoinColumn(name="product_id", referencedColumnName="id")
         *   },
         *   inverseJoinColumns={
         *     @ORM\JoinColumn(name="set_id", referencedColumnName="id")
         *   }
         * )
         */
        private $set;

        /**
         * @var \Doctrine\Common\Collections\Collection
         *
         * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Products", mappedBy="productParentid")
         */
        private $product;

        /**
         * @var \Doctrine\Common\Collections\Collection
         *
         * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Documents", inversedBy="product")
         * @ORM\JoinTable(name="product_attachments",
         *   joinColumns={
         *     @ORM\JoinColumn(name="product_id", referencedColumnName="id")
         *   },
         *   inverseJoinColumns={
         *     @ORM\JoinColumn(name="document_id", referencedColumnName="id")
         *   }
         * )
         */
        private $document;

        /**
         * @var \Doctrine\Common\Collections\Collection
         *
         * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Images", inversedBy="product")
         * @ORM\JoinTable(name="products_images",
         *   joinColumns={
         *     @ORM\JoinColumn(name="product_id", referencedColumnName="id")
         *   },
         *   inverseJoinColumns={
         *     @ORM\JoinColumn(name="image_id", referencedColumnName="id")
         *   }
         * )
         */
        private $image;

        // CUSTOM CODE
        /** 
         * @ORM\OneToMany(targetEntity="AppBundle\Entity\ProviderRate", mappedBy="product", cascade={"persist"})
         */
        private $providerRate;

        /**
         * Constructor
         */
        public function __construct() {
            $this->createdtime      = new \DateTime();
            $this->modifiedtime     = new \DateTime();
            $this->set              = new \Doctrine\Common\Collections\ArrayCollection();
            $this->product          = new \Doctrine\Common\Collections\ArrayCollection();
            $this->document         = new \Doctrine\Common\Collections\ArrayCollection();
            $this->image            = new \Doctrine\Common\Collections\ArrayCollection();
            $this->providerRate     = new \Doctrine\Common\Collections\ArrayCollection();
            $this->descriptionLong  = '';
            $this->amountPerUnit    = 1;
            $this->web              = '';
            $this->weight           = 0;
            $this->isdeleted        = 0;
        }


        /**
         * Set name
         *
         * @param string $name
         * @return Products
         */
        public function setName($name) {
            $this->name = $name;

            return $this;
        }

        /**
         * Get name
         *
         * @return string 
         */
        public function getName() {
            return $this->name;
        }

        /**
         * Set description
         *
         * @param string $description
         * @return Products
         */
        public function setDescription($description) {
            $this->description = $description;

            return $this;
        }

        /**
         * Get description
         *
         * @return string 
         */
        public function getDescription() {
            return $this->description;
        }

        /**
         * Set code
         *
         * @param string $code
         * @return Products
         */
        public function setCode($code) {
            $this->code = $code;

            return $this;
        }

        /**
         * Get code
         *
         * @return string 
         */
        public function getCode() {
            return $this->code;
        }

        /**
         * Set descriptionLong
         *
         * @param string $descriptionLong
         * @return Products
         */
        public function setDescriptionLong($descriptionLong) {
            $this->descriptionLong = $descriptionLong;

            return $this;
        }

        /**
         * Get descriptionLong
         *
         * @return string 
         */
        public function getDescriptionLong() {
            return $this->descriptionLong;
        }

        /**
         * Set amountPerUnit
         *
         * @param integer $amountPerUnit
         * @return Products
         */
        public function setAmountPerUnit($amountPerUnit) {
            $this->amountPerUnit = $amountPerUnit;

            return $this;
        }

        /**
         * Get amountPerUnit
         *
         * @return integer 
         */
        public function getAmountPerUnit() {
            return $this->amountPerUnit;
        }

        /**
         * Set weight
         *
         * @param string $weight
         * @return Products
         */
        public function setWeight($weight) {
            $this->weight = $weight;

            return $this;
        }

        /**
         * Get weight
         *
         * @return string 
         */
        public function getWeight() {
            return $this->weight;
        }

        /**
         * Set web
         *
         * @param string $web
         * @return Products
         */
        public function setWeb($web) {
            $this->web = $web;

            return $this;
        }

        /**
         * Get web
         *
         * @return string 
         */
        public function getWeb() {
            return $this->web;
        }

        /**
         * Set isactive
         *
         * @param boolean $isactive
         * @return Products
         */
        public function setIsactive($isactive) {
            $this->isactive = $isactive;

            return $this;
        }

        /**
         * Get isactive
         *
         * @return boolean 
         */
        public function getIsactive() {
            return $this->isactive;
        }

        /**
         * Set createdtime
         *
         * @param \DateTime $createdtime
         * @return Products
         */
        public function setCreatedtime($createdtime) {
            $this->createdtime = $createdtime;

            return $this;
        }

        /**
         * Get createdtime
         *
         * @return \DateTime 
         */
        public function getCreatedtime() {
            return $this->createdtime;
        }

        /**
         * Set modifiedtime
         *
         * @param \DateTime $modifiedtime
         * @return Products
         */
        public function setModifiedtime($modifiedtime) {
            $this->modifiedtime = $modifiedtime;

            return $this;
        }

        /**
         * Get modifiedtime
         *
         * @return \DateTime 
         */
        public function getModifiedtime() {
            return $this->modifiedtime;
        }

        /**
         * Set deletedtime
         *
         * @param \DateTime $deletedtime
         * @return Products
         */
        public function setDeletedtime($deletedtime) {
            $this->deletedtime = $deletedtime;

            return $this;
        }

        /**
         * Get deletedtime
         *
         * @return \DateTime 
         */
        public function getDeletedtime() {
            return $this->deletedtime;
        }

        /**
         * Set isdeleted
         *
         * @param boolean $isdeleted
         * @return Products
         */
        public function setIsdeleted($isdeleted) {
            $this->isdeleted = $isdeleted;

            return $this;
        }

        /**
         * Get isdeleted
         *
         * @return boolean 
         */
        public function getIsdeleted() {
            return $this->isdeleted;
        }

        /**
         * Get id
         *
         * @return integer 
         */
        public function getId() {
            return $this->id;
        }

        /**
         * Set category
         *
         * @param \AppBundle\Entity\Categories $category
         * @return Products
         */
        public function setCategory(\AppBundle\Entity\Categories $category = null) {
            $this->category = $category;

            return $this;
        }

        /**
         * Get category
         *
         * @return \AppBundle\Entity\Categories 
         */
        public function getCategory() {
            return $this->category;
        }

        /**
         * Set type
         *
         * @param \AppBundle\Entity\ProductTypes $type
         * @return Products
         */
        public function setType(\AppBundle\Entity\ProductTypes $type = null) {
            $this->type = $type;

            return $this;
        }

        /**
         * Get type
         *
         * @return \AppBundle\Entity\ProductTypes 
         */
        public function getType() {
            return $this->type;
        }

        /**
         * Set currency
         *
         * @param \AppBundle\Entity\Currencies $currency
         * @return Products
         */
        public function setCurrency(\AppBundle\Entity\Currencies $currency = null) {
            $this->currency = $currency;

            return $this;
        }

        /**
         * Get currency
         *
         * @return \AppBundle\Entity\Currencies 
         */
        public function getCurrency() {
            return $this->currency;
        }

        /**
         * Add set
         *
         * @param \AppBundle\Entity\Sets $set
         * @return Products
         */
        public function addSet(\AppBundle\Entity\Sets $set) {
            $this->set[] = $set;

            return $this;
        }

        /**
         * Remove set
         *
         * @param \AppBundle\Entity\Sets $set
         */
        public function removeSet(\AppBundle\Entity\Sets $set) {
            $this->set->removeElement($set);
        }

        /**
         * Get set
         *
         * @return \Doctrine\Common\Collections\Collection 
         */
        public function getSet() {
            return $this->set;
        }

        /**
         * Add product
         *
         * @param \AppBundle\Entity\Products $product
         * @return Products
         */
        public function addProduct(\AppBundle\Entity\Products $product) {
            $this->product[] = $product;

            return $this;
        }

        /**
         * Remove product
         *
         * @param \AppBundle\Entity\Products $product
         */
        public function removeProduct(\AppBundle\Entity\Products $product) {
            $this->product->removeElement($product);
        }

        /**
         * Get product
         *
         * @return \Doctrine\Common\Collections\Collection 
         */
        public function getProduct() {
            return $this->product;
        }

        /**
         * Add document
         *
         * @param \AppBundle\Entity\Documents $document
         * @return Products
         */
        public function addDocument(\AppBundle\Entity\Documents $document) {
            $this->document[] = $document;

            return $this;
        }

        /**
         * Remove document
         *
         * @param \AppBundle\Entity\Documents $document
         */
        public function removeDocument(\AppBundle\Entity\Documents $document) {
            $this->document->removeElement($document);
        }

        /**
         * Get document
         *
         * @return \Doctrine\Common\Collections\Collection 
         */
        public function getDocument() {
            return $this->document;
        }

        /**
         * Add image
         *
         * @param \AppBundle\Entity\Images $image
         * @return Products
         */
        public function addImage(\AppBundle\Entity\Images $image) {
            $this->image[] = $image;

            return $this;
        }

        /**
         * Remove image
         *
         * @param \AppBundle\Entity\Images $image
         */
        public function removeImage(\AppBundle\Entity\Images $image) {
            $this->image->removeElement($image);
        }

        /**
         * Get image
         *
         * @return \Doctrine\Common\Collections\Collection 
         */
        public function getImage() {
            return $this->image;
        }

        // CUSTOM CODE
        /**
         * Set providerRate
         *
         * @param \AppBundle\Entity\ProviderRate $providerRate
         * @return Products
         */
     /*   public function setProviderRate(\AppBundle\Entity\ProviderRate $providerRate = null)
        {
            $this->providerRate = $providerRate;

            return $this;
        }
    */
         /**
         * Add providerRate
         *
         * @param \AppBundle\Entity\ProviderRate $providerRate
         * @return Products
         */
        public function addProviderRate(\AppBundle\Entity\ProviderRate $providerRate) {
            $this->providerRate[] = $providerRate;

            return $this;
        }

        /**
         * Remove providerRate
         *
         * @param \AppBundle\Entity\ProviderRate $providerRate
         */
        public function removeProviderRate(\AppBundle\Entity\ProviderRate $providerRate) {
            $this->providerRate->removeElement($providerRate);
        }

        /**
         * Get providerRate
         *
         * @return \AppBundle\Entity\ProviderRate 
         */
        public function getProviderRate()
        {
            return $this->providerRate;
        }
    }

ProviderRate Entity

  /**
     * ProviderRate
     *
     * @ORM\Table(name="provider_rate", indexes={@ORM\Index(name="fk_proveedor_has_producto_compra_producto_compra1_idx", columns={"product_id"}), @ORM\Index(name="fk_id_tarifa_proveedor_id_moneda1_idx", columns={"currency_id"}), @ORM\Index(name="IDX_3A645C45A53A8AA", columns={"provider_id"})})
     * @ORM\Entity(repositoryClass="AppBundle\Repository\ProviderRateRepository")
     */
    class ProviderRate
    {
        /**
         * @var string
         *
         * @ORM\Column(name="reference", type="string", length=45, nullable=false)
         */
        private $reference;

        /**
         * @var string
         *
         * @ORM\Column(name="name", type="string", length=45, nullable=false)
         */
        private $name;

        /**
         * @var string
         *
         * @ORM\Column(name="description", type="string", length=255, nullable=false)
         */
        private $description;

        /**
         * @var integer
         *
         * @ORM\Column(name="amount_per_unit", type="integer", nullable=true)
         */
        private $amountPerUnit;

        /**
         * @var string
         *
         * @ORM\Column(name="unit_price", type="decimal", precision=25, scale=3, nullable=false)
         */
        private $unitPrice;

        /**
         * @var string
         *
         * @ORM\Column(name="discount", type="decimal", precision=25, scale=3, nullable=false)
         */
        private $discount;

        /**
         * @var \AppBundle\Entity\Providers
         *
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="NONE")
         * @ORM\OneToOne(targetEntity="AppBundle\Entity\Providers")
         * @ORM\JoinColumns({
         *   @ORM\JoinColumn(name="provider_id", referencedColumnName="id")
         * })
         */
        private $provider;

        /**
         * @var \AppBundle\Entity\Products
         *
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="NONE")
         * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Products", inversedBy="providerRate")
         * @ORM\JoinColumn(name="product_id", referencedColumnName="id")
         * 
         */
        private $product;


        /**
         * Set provider
         *
         * @param \AppBundle\Entity\Providers $provider
         * @return ProviderRate
         */
        public function setProvider(\AppBundle\Entity\Providers $provider)
        {
            $this->provider = $provider;

            return $this;
        }

        /**
         * Get provider
         *
         * @return \AppBundle\Entity\Providers 
         */
        public function getProvider()
        {
            return $this->provider;
        }

        /**
         * Set product
         *
         * @param \AppBundle\Entity\Products $product
         * @return ProviderRate
         */
        public function setProduct(\AppBundle\Entity\Products $product)
        {
            $this->product = $product;

            return $this;
        }

        /**
         * Get product
         *
         * @return \AppBundle\Entity\Products 
         */
        public function getProduct()
        {
            return $this->product;
        }

    }

The code to run on the controller is as follows:

public function ajaxNewProductAction() {
        $request = $this->getRequest();

        $product    = new Products();
        $form       = $this->createForm(new ProductsType(), $product);
        $form->handleRequest($request);
        if ($request->getMethod() == 'POST') {
            if ($form->isSubmitted() && $form->isValid()) { // Se procesa el formulario
                $em             = $this->getDoctrine()->getManager();
                $providerId     = $request->get('provider');
                $productVals    = $request->get('Products');
                $currency       = $em->getRepository('AppBundle:Currencies')->findOneByName("Euro");

                $product->setCurrency($currency);
                $product->setType($em->getRepository('AppBundle:ProductTypes')->findOneById(1));
                $product->setIsactive(1);

                $em->persist($product);
                $em->flush();


                $response['success'] = true;
                $response['data'] = 0;
                $response['providerId'] = $providerId;
            }
            else {
                $response['success'] = false;
                $response['cause'] = 'whatever';
            }
            return new JsonResponse($response);
        }

        return $this->render(':products/ajax:newProduct.html.twig', array("form" => $form->createView(), "edit" => false));
    }
1

There are 1 best solutions below

0
On BEST ANSWER

SOLVE:

I can solve it. The code of my entities thats ok. I change the controller function. First I create the product object, set the providerRate to null and them persist it. After I create the providerRate object and set the product object.

public function ajaxNewProductAction() {
        $request = $this->getRequest();

        $product    = new Products();
        $form       = $this->createForm(new ProductsType(), $product);
        $form->handleRequest($request);
        if ($request->getMethod() == 'POST') {
            if ($form->isSubmitted() && $form->isValid()) { // Se procesa el formulario
                $em             = $this->getDoctrine()->getManager();
                $providerId     = $request->get('provider');
                $productVal     = $request->get('Products');
                $currency       = $em->getRepository('AppBundle:Currencies')->findOneByName("Euro");

                $product->setCurrency($currency);
                $product->setType($em->getRepository('AppBundle:ProductTypes')->findOneById(1));
                $product->setProviderRate(null);
                $em->persist($product);
                $em->flush();

                $providerRate = new ProviderRate();
                $providerRate->setProvider($em->getRepository('AppBundle:Providers')->findOneById($providerId));
                $providerRate->setProduct($product);
                $providerRate->setReference($productVal["providerRate"][1]["reference"]);
                $providerRate->setName($productVal["name"]);
                $providerRate->setDescription($productVal["description"]);
                $providerRate->setAmountPerUnit(1);
                $providerRate->setUnitPrice(0);
                $providerRate->setDiscount(0);
                $providerRate->setCurrency($currency);

                $providerRate->setProduct($product);
                $em->persist($providerRate);
                $em->flush();

                $response['success'] = true;
            }
            else {
                $response['success'] = false;
                $response['cause'] = 'Algo ocurrió';
            }
            return new JsonResponse($response);
        }

        return $this->render(':products/ajax:newProduct.html.twig', array("form" => $form->createView(), "edit" => false));
    }