C0ol_Cod3r
C0ol_Cod3r

Reputation: 949

Symfony 2.7 form builder with new field from another entity?

So I start off with my database layout, I have a User table which has an accounts_id link to another table Accounts.

Inside Accounts I have companyname. Now I have built a AbstractType for my user sign up. I want this form to include a field for companyname. But what I have tried is not working, so where is what I have done so far,

use XBundle\Form\AccountType;

class UserType extends AbstractType {

  public function buildForm(FormBuilderInterface $builder, array $options) {

    $builder->add('firstname', 'text',['label'=>'Firstname'])
            ->add('surname', 'text',['label'=>'Surname'])

            //->add('companyname','text', ['data_class' => 'XBundle\Entity\Accounts'])

            ->add('companyname', new AccountType()) <- current attempt

            ->add('email', 'email',['label'=>'Email'])
            ->add('password', 'password',['label'=>'Password']);

            //->add('confirm', 'password', ['mapped' => false,'label'=>'Re-type password'])
            //->add('homepage', 'text',['label'=>'Homepage'])

            //->add('save', 'submit', ['label'=>'Register']);
  }

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

  public function configureOptions(OptionsResolver $resolver) {
    $resolver->setDefaults([
        'data_class' => 'XBundle\Entity\Users',
        'cascade_validation' => true,
    ]);
  }
}

And for my AccountType I have the following,

class AccountType extends AbstractType {

  public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder
            ->add('companyname','text', ['label'=>'Company']);       
  }

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

  public function configureOptions(OptionsResolver $resolver) {
    $resolver->setDefaults([
        'data_class' => 'XBundle\Entity\Accounts',
    ]);
  }
}

When I build a createForm & createView for my twig (which renders without any problems without the companyname / AccountType). I get the following error,

Neither the property "companyname" 
nor one of the methods "getCompanyname()", 
"companyname()", "isCompanyname()", "hasCompanyname()", 
"__get()" exist and have public access in class "XBundle\Entity\Users"

Now I know that companyname is in my Accounts Entity. I have also done a test to make sure my AccountType works, by building a new form with that type, which renders the Company Name field without any problems.

But I am not sure what I am doing wrong, or even if this is the right way about going about adding another entities field on my user sign up form, please help :)

Upvotes: 2

Views: 1535

Answers (1)

giosh94mhz
giosh94mhz

Reputation: 3116

The error you get is expected.

AccountType is a form to edit Account entity details. By adding companyname to the builder you explicily say that setters and getters exists for that property. An this part is correct.

UserType is a form to edit User entity details, NOT Account details. If you add an AccountType property named companyname,the form component expect you to provide these methods:

public function getCompanyname() {/*...*/}
public function setCompanyname(Account $account) {/*...*/}

Which is not what you are expecting, and exactly what the error is saying.

You need to provide accessor for the Account to your user entity, and then define how the form should handle it.

Option 1: you want to select an existing account

Add this to the UserType builder:

public function buildForm(FormBuilderInterface $builder, array $options) {
    // options are guessed anyway, you choose if set it explicitly or not
    $builder->add('account'/*, 'entity', array(
        'class' => 'XBundle:Account'
    )*/);
}

And the following to your User entity:

class User {
    private $account;

    public function getAccount() {
        return $this->account;
    }

    public function setAccount(Account $account /* = null, if optional */) {
        $this->account = $account;
    }
}

Option 2: you want one-to-one association and an editable account

Add this to the UserType builder:

public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder->add('account', new AccountType());
}

And the following to your User entity:

class User {
    private $account;

    public function __construct() {
        $this->account = new Account();
    }

    public function getAccount() {
        return $this->account;
    }
}

Upvotes: 3

Related Questions