Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony - Pasing values from One Form to another

I've read everything about Symfony forms and Twig, but haven't found any solution for my problem, so I decided to ask you guys.

What I'm trying to achieve is to pass duplicate data to my registration form only once. Data that I want to persist in database are user details, company name and address and branch name and address. I need to copy address details to two entities i.e. Company and Branch.

Is there a way to pass this data to form in web interface only once and point it to two Symfony forms to be added to entities and validated.

I know I can copy address data from one entity to another outside of the form, but it doesn't feel right.

Main RegistrationFormType:

class RegistrationFormType extends AbstractType
{
    private $class;

    public function __construct($class)
    {
        $this->class = $class;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('first_name')
            ->add('last_name')
            ->add('username')
            ->add('email', 'email')
            ->add('password', 'password')
            ->add('company', new CompanyType())
            ->add('branch', new BranchType())
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => $this->class,
            'intention'  => 'registration',
        ));
    }

    public function getName()
    {
        return 'registration';
    }
}

CompanyType:

class CompanyType extends AbstractType
{   
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('companyName')
            ->add('foo', new CompanyInfoType(), array('data_class' => 'Acme\UserBundle\Entity\Company'))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\UserBundle\Entity\Company',
            'validation_groups' => array('Registration'),
        ));
    }

    public function getName()
    {
        return 'company';
    }
}

Branch Type:

class BranchType extends AbstractType
{   
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('branchName')
            ->add('boo', new CompanyInfoType(), array('data_class' => 'Acme\UserBundle\Entity\Branch'))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\UserBundle\Entity\Branch',
            'validation_groups' => array('Registration'),
        ));
    }

    public function getName()
    {
        return 'branch';
    }
}

CompanyInfoType:

class CompanyInfoType extends AbstractType
{   
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('streetNumber')
            ->add('address')
            ->add('city')
            ->add('zip')
            ->add('country')
            ->add('contactName')
            ->add('phone')
            ->add('email')
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'inherit_data' => true
        ));
    }

    public function getName()
    {
        return 'company_info';
    }
}

Thanks!

// EDIT

I just want to explain why I want to copy company details to branch since it does look a little a bit weird.

It is done that way just because I want to have structure prepared in case customer wants to upgrade their account to "enterprise". With default registration they basically have only one branch which is equal to company HQ and if they add more branches, company details stay the same since that's their main "branch". The existing users and other stuff is already mapped to that branch, so adding new branch doesn't require any database or other structural changes.

// EDIT2 I managed to get this working inside form thanks to linuxatico, but I'm sure it can be solved even prettier. Here is how I did it:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('first_name')
        ->add('last_name')
        ->add('username')
        ->add('email', 'email')
        ->add('password', 'password')
        ->add('company', new CompanyType())
        ->add('branch', new BranchType())
    ;

    $builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
        $company = $event->getForm()->get('company')->getData();
        $event->getForm()->get('branch')->getData()
            ->setBranchName($company->getCompanyName())
            ->setStreetNumber($company->getStreetNumber())
            ->setAddress($company->getAddress())
            ->setCity($company->getCity())
            ->setCountry($company->getCountry())
            ->setZip($company->getZip())
            ->setContactName($company->getContactName())
        ;
    });
}
like image 949
darac Avatar asked Oct 20 '22 09:10

darac


1 Answers

Well, I don't think it's a good idea what you're doing, by the info you gave us it seems you have a structural problem on how you design your software and there sure is another better way to solve your problem.

Anyway, if you want to go on with your solution, I can suggest the use of AJAX, preferably JQuery, so that you can make a POST request to the second form if the first goes right.

In pseudocode:

$.post({ url1,
         key_value_array_data,
         function(){
             $.post({ url2,
                      key_value_array_data,
                      function(){
                           //custom_code
                    });
        }
}); 

EDIT: this will sure help: https://api.jquery.com/serialize/

EDIT #2: Tou can also use Symfony's internal Event system to intercept the form submission and customize the behaviour as you wish: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

like image 76
linuxatico Avatar answered Oct 23 '22 04:10

linuxatico