[symfony3] 1 FORM et 2 ENTITY [Fermé]

Signaler
Messages postés
65
Date d'inscription
dimanche 1 février 2009
Statut
Membre
Dernière intervention
22 juin 2020
-
 Utilisateur anonyme -
Bonjour,
je suis entrain de suivre un tutoriel de symfony3, créeation d'un formulaire, mais dans mon cas il s'agit de deux entités et pas une.
voici un bout de code de mon controleur:
 public function addAction(Request $request)
{
// On crée un objet Advert
$advert = new Advert();
$customer = new Customer();
// On crée le FormBuilder grâce au service form factory
$formBuilder = $this->get('form.factory')->createBuilder(FormType::class, $advert, $customer);
// On ajoute les champs de l'entité que l'on veut à notre formulaire
$formBuilder
->add('title', TextType::class)
->add('content', TextareaType::class)
->add('published', CheckboxType::class)
//->add('lname', TextType::class)
//->add('fname', TextType::class)
->add('save', SubmitType::class)
;
$form = $formBuilder->getForm();
// On passe la méthode createView() du formulaire à la vue
// afin qu'elle puisse afficher le formulaire toute seule
return $this->render('xxxBundle:Advert:add.html.twig', array(
'form' => $form->createView(),
));
// Si on n'est pas en POST, alors on affiche le formulaire
//return $this->render('xxxBundle:Advert:add.html.twig');

}


alors, lorsque j'ajoute $customer après $advert et je décommente, ce message d'erreur s'affiche:
Catchable Fatal Error: Argument 3 passed to Symfony\Component\Form\FormFactory::createBuilder() must be of the type array, object given, called in C:\wamp\www\myapp\src\xx\xxxBundle\Controller\AdvertController.php on line 64 and defined
bien sur la ligne 64 dans mon controleur c'est :
$formBuilder = $this->get('form.factory')->createBuilder(FormType::class, $advert, $customer);

ma question, comment puis je hydrater deux objets (entites) avec le meme formulaire?
merci d'avance pour votre aide.

3 réponses

Salut,

je me demande pourquoi tu souhaites hydrater un objet Advert (article) et un objet customer (client) avec un même formulaire.

Le formulaire que tu présentes semble être destiné à un advert et un advert est j'imagine en relation avec un customer.
Est-ce que ton entité customer dispose de champs title, content, published ?

Peux tu nous montrer le mapping qu'il y a pour les entités advert et customer ?
Messages postés
65
Date d'inscription
dimanche 1 février 2009
Statut
Membre
Dernière intervention
22 juin 2020
1
merci while(coding)returnhappy()
je joue sur la simplicité & la rapidité: le minimum nécessaire d'information, ce ui explique la présence de deux objets dans le meme formulaire.
remarque: 1)
il y aura une page pour compléter quelques champs optionnels tels que: tel,city, ...
2)j ai pas encore décidé est ce que je le garde ou non le champ category,
Question: comment faire pour hydrater ces deux objets en garadnt le meme principe mentionné ci-dessus.
merci
entité advert
<?php

namespace XX\xxxBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * Advert
 *
 * @ORM\Table(name="Advert")
 * @ORM\Entity(repositoryClass="XX\xxxBundle\Repository\AdvertRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class Advert
{
    /**
     * @ORM\ManyToOne(targetEntity="XX\xxxBundle\Entity\Category")
     * @ORM\JoinColumn(nullable=false)
     */
    private $category;
    
    /**
     * @ORM\ManyToOne(targetEntity="XX\xxxBundle\Entity\Customer")
     * @ORM\JoinColumn(nullable=false)
     */
    private $customer;    
  
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

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


    /**
     * @var int
     *
     * @ORM\Column(name="nbview", type="smallint")
     */
    private $nbview=0;

    /**
     * @var int
     *
     * @ORM\Column(name="alert", type="smallint")
     */
    private $alert;

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

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="dateedit", type="datetime", nullable=true)
     */
    private $dateedit;
    
    
    /**
     * @ORM\OneToMany(targetEntity="XX\xxxBundle\Entity\Picture", mappedBy="advert", cascade={"persist"})
    */
    private $picture;

    /**
     * @var \boolean
     *
     * @ORM\Column(name="published", type="boolean")
     */
    private $published;    
      
    public function __construct()
    {
        $this->datecreate = new \DateTime('now');
        $this->published=true;
        $this->picture = new \Doctrine\Common\Collections\ArrayCollection();
    }
    
    /**
     * Get id
     *
     * @return int
     */   
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set title
     *
     * @param string $title
     *
     * @return advert
     */
    public function setTitle($title)
    {
        $this->title = $title;
        return $this;
    }

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

    /**
     * Set content
     *
     * @param string $content
     *
     * @return advert
     */
    public function setContent($content)
    {
        $this->content = $content;
        return $this;
    }

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


    /**
     * Set advert
     *
     * @param \XX\xxxBundle\Entity\Advert $advert
     *
     * @return Advert
     */
    public function setAdvert(\XX\xxxBundle\Entity\Advert $advert)
    {
        $this->advert = $advert;
        return $this;
    }

    /**
     * Get advert
     *
     * @return \XX\xxxBundle\Entity\Advert
     */
    public function getAdvert()
    {
        return $this->advert;
    }

    /**
     * Set category
     *
     * @param \XX\xxxBundle\Entity\Category $category
     *
     * @return Advert
     */
    public function setCategory(\XX\xxxBundle\Entity\Category $category)
    {
        $this->category = $category;
        return $this;
    }

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



    public function setNbview($nbview)
    {
        $this->nbview = $nbview;
        return $this;
    }

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

    /**
     * Set alert
     *
     * @param integer $alert
     *
     * @return Advert
     */
    public function setAlert($alert)
    {
        $this->alert = $alert;
        return $this;
    }

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

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

    /**
     * @ORM\PreUpdate
     */
    public function setDateedit()
    {
        $this->setUpdatedAt(new \Datetime());
        return $this;
    }

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

    /**
     * Set published
     *
     * @param boolean $published
     *
     * @return Advert
     */
    public function setPublished($published)
    {
        $this->published = $published;
        return $this;
    }

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

    /**
     * Set customer
     *
     * @param \XX\xxxBundle\Entity\Customer $customer
     *
     * @return Advert
     */
    public function setCustomer(\XX\xxxBundle\Entity\Customer $customer)
    {
        $this->customer = $customer;
        return $this;
    }

    /**
     * Get customer
     *
     * @return \XX\xxxBundle\Entity\Customer
     */
    public function getCustomer()
    {
        return $this->customer;
    }

 
    public function addPicture(\XX\xxxBundle\Entity\Picture $picture)
    {
        $this->picture[] = $picture;
        $picture->setAdvert($this);
        return $this;
    }
 
    public function removePicture(\XX\xxxBundle\Entity\Picture $picture)
    {
        $this->picture->removeElement($picture);
    }
 
    public function getPicture()
    {
        return $this->picture;
    }
}

entité customer
<?php

namespace xx\XXXBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Customer
 *
 * @ORM\Table(name="customer")
 * @ORM\Entity(repositoryClass="xx\XXXBundle\Repository\CustomerRepository")
 */
class Customer
{



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

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

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

    /**
     * @var string
     *
     * @ORM\Column(name="city", type="string", length=255, nullable=true)
     */
    private $city;  
    
    /**
     * @var int
     *
     * @ORM\Column(name="tel", type="integer", nullable=true)
     */
    private $tel;


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

    /**
     * Set lname
     *
     * @param string $lname
     *
     * @return Customer
     */
    public function setLname($lname)
    {
        $this->lname = $lname;

        return $this;
    }

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

    /**
     * Set fname
     *
     * @param string $fname
     *
     * @return Customer
     */
    public function setFname($fname)
    {
        $this->fname = $fname;

        return $this;
    }

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

    /**
     * Set city
     *
     * @param string $city
     *
     * @return Customer
     */
    public function setCity($city)
    {
        $this->city = $city;

        return $this;
    }

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

    /**
     * Set tel
     *
     * @param integer $tel
     *
     * @return Customer
     */
    public function setTel($tel)
    {
        $this->tel = $tel;

        return $this;
    }

    /**
     * Get tel
     *
     * @return int
     */
    public function getTel()
    {
        return $this->tel;
    }

}
ha ok, j'ai compris...

Le plus simple est d'imbriquer un formulaire customerType dans un advertType.

exemple :

advertType :

class AdvertType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array                $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title', TextType::class)
            ->add('content', TextareaType::class)
            ->add('published', CheckboxType::class)
            ->add('customer', CustomerType::class)
            ->add('save', SubmitType::class);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(
            [
                'data_class' => Advert::class,
            ]
        );
    }
}


customerType :

class CustomerType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array                $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('lname', TextType::class)
            ->add('fname', TextType::class);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(
            [
                'data_class' => Customer::class,
            ]
        );
    }
}



controller

 public function addAction(Request $request)
    {
        $advert   = new Advert();
        $customer = new Customer();
        $advert->setCustomer($customer);

        $form = $this->createForm(AdvertType::class, $advert);
        $form->handleRequest($request);
        if ($form->isValid()) {

            // bla bla
        }

        return $this->render('xxxBundle:Advert:add.html.twig', ['form' => $form->createView()]);
    }



je n'ai pas testé, il se peut que cela ne fonctionne pas directement, mais l'idée est là.
Messages postés
65
Date d'inscription
dimanche 1 février 2009
Statut
Membre
Dernière intervention
22 juin 2020
1
merci beaucoup while(coding)returnhappy(); tu m'as sauvé :)
je teste ta solution puis je te tiens au courant.
Messages postés
65
Date d'inscription
dimanche 1 février 2009
Statut
Membre
Dernière intervention
22 juin 2020
1
bonsoir,
voici la solution pour avoir des FORMULAIRES IMBRIQUES
advertType:
<?php

namespace xx\XXXBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
//
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
//

class AdvertType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('title',       TextType::class)
                ->add('content',     TextareaType::class)
                ->add('picture',     PictureType::class, array('data_class' => null))
                ->add('published',   CheckboxType::class, array('required' => false))
                ->add('category',    EntityType::class, array(
                            'class'        => 'xxXXXBundle:Category',
                            'choice_label' => 'longname',
                            'multiple'     => false,
                            'expanded'     => false,
                      ))
                 
                ->add('customer',    CustomerType::class)
                ->add('save',        SubmitType::class)
        ;
    }
    
    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'xx\XXXBundle\Entity\Advert'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'xx_XXXbundle_advert';
    }


}

customerType
<?php

namespace xx\XXXBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
//use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
//
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
//

class CustomerType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('lnamecust',       TextType::class)
                ->add('fnamecust',       TextType::class)
                ->add('telcust',         TextType::class)
                ->add('governate',       EntityType::class, array(
                            'class'        => 'xxXXXBundle:Governate',
                            'choice_label' => 'name',
                            'multiple'     => false,
                            'expanded'     => false, 
                      ))
                ;
    }
    
    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'xx\XXXBundle\Entity\Customer'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'xx_XXXbundle_customer';
    }


}

et pictureType
<?php

namespace xx\XXXBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\FileType;

class PictureType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('file', FileType::class)        ;
    }
    
    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'xx\XXXBundle\Entity\Picture'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'XX_xxxbundle_picture';
    }


}

deux questions:
1)puisque le formulaire est créer automatiquement comment faire pour le personnaliser avec les CSS (de mon template) .
2)est ce qu'il faut créer un et un seul xxxType pour une entite XXX. car je veux hydrater au début deux champs de customer avec le formulaire1, puis optionnellement compléter les autres informations via un autre formulaire2 (sachant que l'entité customer possède 4 champs à remplir manuellement).
merci encore.
1)puisque le formulaire est créer automatiquement comment faire pour le personnaliser avec les CSS (de mon template) .

tu peux utiliser "attr" exemple :

        $builder->add('file', FileType::class, ['attr' => ['class' => 'btn btn-default']]);


https://symfony.com/doc/current/reference/forms/types/form.html#attr

pour les labels : https://symfony.com/doc/current/reference/forms/types/form.html#label-attr


2)est ce qu'il faut créer un et un seul xxxType pour une entite XXX. car je veux hydrater au début deux champs de customer avec le formulaire1, puis optionnellement compléter les autres informations via un autre formulaire2 (sachant que l'entité customer possède 4 champs à remplir manuellement).
merci encore.

Dans ton cas tu peux soit
- en créer 2
- soit mettre 2 champs supplémentaire dans ton seul et unique formulaire avec l'attribut mapped à false, puis hydrater ton entité dans le controller en récupérant les valeurs de ces deux champs
.
https://symfony.com/doc/current/reference/forms/types/form.html#mapped