phpdatabaseformssymfony

How to insert data into two table have a single form type in symfony?


enter image description hereenter image description hereI have a single form which inserts data in following table:

Note: I have not created address as FK in Vendor table but it does saves the id for address table.

I made this form class by reference of docs: https://symfony.com/doc/current/form/embedded.html

VendorType form class:

class VendorType extends AbstractType {
     public function buildForm(FormBuilderInterface $builder, array $options)  
     {  
         $builder
             ->add('first_name',TextType::class,[
                 'attr' => [
                     'placeholder' => 'Enter First name',
                 ]
             ])  
             ->add('last_name',TextType::class,[
                 'attr' => [
                     'placeholder' => 'Enter Last name'
                 ]
             ])  
             ->add('address',TextAreaType::class,[
                 'attr' => [
                     'placeholder' => 'Enter your current address'
                 ],
                 'mapped' => false,
                 //if given then value wont be fetched for address in entity object.
             ])  
             ->add('city',TextType::class,[
                 'attr' => [
                     'placeholder' => 'Enter city'
                 ]
             ])  
             ->add('state',TextType::class,[
                 'attr' => [
                     'placeholder' => 'Enter state'
                 ]
             ])  
             ->add('country',TextType::class,[
                 'attr' => [
                     'placeholder' => 'Enter country'
                 ]
             ])  
             ->add('pincode',TextType::class,[
                 'attr' => [
                     'placeholder' => 'Enter Pincode'
                 ]
             ])  
             ->add('Save',SubmitType::class,[
                 'attr' => [
                     'class' => 'btn btn-success'
                 ]
             ])  

         ;  
     }  

     public function configureOptions(OptionsResolver $resolver)  
     {  
         $resolver->setDefaults([
             'data_class' => Vendor::class,
         ]);
     }  

Controller:  

$vendor = new Vendor();  
        $manager = $this->getDoctrine()->getManager();  
        $vendorForm = $this->createForm(VendorType::class, $vendor);  

        $vendorForm->handleRequest($request);  

        if ($vendorForm->isSubmitted()) {
            if ($vendorForm->isValid()) {
                $address = new Address;

                $address->setAddress($request->request->get('vendor')['address']);
                $address->setCity($request->request->get('vendor')['city']);
                $address->setState($request->request->get('vendor')['state']);
                $address->setCountry($request->request->get('vendor')['country']);
                $address->setPincode($request->request->get('vendor')['pincode']);


                $manager->persist($address);
                $manager->flush();
                if(null != $address->getId()){

                    $vendor->setFirstName($request->request->get('vendor')['first_name']);

                    $vendor->setLastName($request->request->get('vendor')['last_name']);

                    $vendor->setAddress($address->getId());
                    // dump($ven);
                    // die('uygyu');
                    $manager->persist($vendor);

                    $manager->flush();

                    $this->addFlash('success', 'Article Created! Knowledge is power!');
                }     
            }

Note: Insertion is successful in Address table but data is not inserted into vendor table due following error.

Error message: An exception occurred while executing 'INSERT INTO vendor (first_name, last_name, address, city, state, country, pincode) VALUES (?, ?, ?, ?, ?, ?, ?)' with params ["miss", "Negi", 62, null, null, null, null]:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'city' in 'field list'

How can I submit my form data into their respective tables?

Edit: I understand that vendor object has all the properties so it is not able to execute the query. I want to know how this situation can be solved? What else can be done here? and is there any better way to save such kinds of form?

Address Entity:

namespace App\Entity;


/**
 * @ORM\Entity(repositoryClass="App\Repository\AddressRepository")
 */
class Address
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="text")
     */
    private $address;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $city;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $state;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $country;

    /**
     * @ORM\Column(type="integer")
     */
    private $pincode;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $address_type;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Customer", mappedBy="address")
     */
    private $customers;

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

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

    public function getAddress(): ?string
    {
        return $this->address;
    }

    public function setAddress(string $address): self
    {
        $this->address = $address;

        return $this;
    }

    public function getCity(): ?string
    {
        return $this->city;
    }

    public function setCity(string $city): self
    {
        $this->city = $city;

        return $this;
    }

    public function getState(): ?string
    {
        return $this->state;
    }

    public function setState(string $state): self
    {
        $this->state = $state;

        return $this;
    }

    public function getCountry(): ?string
    {
        return $this->country;
    }

    public function setCountry(string $country): self
    {
        $this->country = $country;

        return $this;
    }

    public function getPincode(): ?int
    {
        return $this->pincode;
    }

    public function setPincode(int $pincode): self
    {
        $this->pincode = $pincode;

        return $this;
    }

    public function getAddressType(): ?string
    {
        return $this->address_type;
    }

    public function setAddressType(string $address_type): self
    {
        $this->address_type = $address_type;

        return $this;
    }

    /**
     * @return Collection|Customer[]
     */
    public function getCustomers(): Collection
    {
        return $this->customers;
    }

    public function addCustomer(Customer $customer): self
    {
        if (!$this->customers->contains($customer)) {
            $this->customers[] = $customer;
            $customer->setAddress($this);
        }

        return $this;
    }

    public function removeCustomer(Customer $customer): self
    {
        if ($this->customers->contains($customer)) {
            $this->customers->removeElement($customer);
            // set the owning side to null (unless already changed)
            if ($customer->getAddress() === $this) {
                $customer->setAddress(null);
            }
        }

        return $this;
    }
}

Vendor Entity:

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\VendorRepository")
 */
class Vendor
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $first_name;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $last_name;

   /**
     * @ORM\Column(type="integer")
     */
    private $address;

    /**
     * @ORM\Column(type="string", length=255)
     */
    public $city;

    /**
     * @ORM\Column(type="string", length=255)
     */
    public $state;

    /**
     * @ORM\Column(type="string", length=255)
     */
    public $country;

    /**
     * @ORM\Column(type="integer", length=255)
     */
    public $pincode;

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

    public function getFirstName(): ?string
    {
        return $this->first_name;
    }

    public function setFirstName(string $first_name): self
    {
        $this->first_name = $first_name;

        return $this;
    }

    public function getLastName(): ?string
    {
        return $this->last_name;
    }

    public function setLastName(string $last_name): self
    {
        $this->last_name = $last_name;

        return $this;
    }

    public function getAddress(): ?int
    {
        return $this->address;
    }

    public function setAddress(int $address): self
    {
        $this->address = $address;

        return $this;
    }

    public function getCity(): ?string
    {
        return $this->city;
    }

    public function getState(): ?string
    {
        return $this->state;
    }

    public function getCountry(): ?string
    {
        return $this->country;
    }

    public function getPincode(): ?int
    {
        return $this->pincode;
    }
}

Solution

  • As we can see in provided screenshot, there is only three fields in Vendor table. There is simple error, the form class is not embedded properly, this is not the way to embed one form to another. The concept is to create 2 different form and embed one into another. Here we embed AddressType form class into VendorType form class.

    VendorType form class:

    class VendorType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('first_name',TextType::class,[
                    'attr' => [
                        'placeholder' => 'Enter First name',
                    ]
                ])
                ->add('last_name',TextType::class,[
                    'attr' => [
                        'placeholder' => 'Enter Last name'
                    ]
                ])
                //Embeding AddressType form in VendorType form.
                ->add('address', AddressType::class)
                ->add('Save',SubmitType::class,[
                    'attr' => [
                        'class' => 'btn btn-success'
                    ]
                ])
    
            ;
        }
    

    Note: look for the comment into code above.