Ask your Symfony questions! Pay money and get answers fast! (more info)

Embedded forms not updating Link Tables Symfony

  • SOLVED

We are trying to tie together a Registration module to use the sfGuardUserPlugin. Below is our schema that we have set up. We have a <em>Profiles</em> table that is used as a link between our <em>Contacts</em> table and the SfGuardUser table. From sfGuardUser to Profile it is a 1:1 and the same goes for Profile to Contacts.

schema.yml

Profiles:
actAs: { Timestampable: ~ }
columns:
sf_guard_user_id: { type: integer(4), notnull: true }
contact_id: {type: integer, notnull: true}
relations:
User:
class: sfGuardUser
foreignAlias: Profile
type: one
foreignType: one
local: sf_guard_user_id
foreign: id
Contacts:
alias: Contact
foreignAlias: Profile
type: one
foreignType: one
local: contact_id
foreign: id

Contacts:
actAs: { Timestampable: ~ }
columns:
first_name: { type: string(50) }
last_name: { type: string(50) }
phone1: { type: string(15) }
phone2: { type: string(15) }
email_address: { type: string(100) }
fax: { type: string(15) }


I'm also including my RegisterForm.class.php, which is the register form that we wish to display to the user when they go to become a new user.


class RegisterForm extends sfGuardUserForm
{
public function configure()
{
unset(
$this['is_active'],
$this['is_super_admin'],
$this['updated_at'],
$this['groups_list'],
$this['permissions_list'],
$this['last_login'],
$this['created_at'],
$this['salt'],
$this['algorithm']
);


//Setup password validation
$this->widgetSchema['password'] = new sfWidgetFormInputPassword();
$this->validatorSchema['password']->setOption('required', true);
$this->widgetSchema['password_confirmation'] = new sfWidgetFormInputPassword();
$this->validatorSchema['password_confirmation'] = clone $this->validatorSchema['password'];

$this->widgetSchema->moveField('password_confirmation', 'after', 'password');

$this->mergePostValidator(new sfValidatorSchemaCompare('password', sfValidatorSchemaCompare::EQUAL, 'password_confirmation', array(), array('invalid'=> 'The passwords you entered do not mat
$this->embedForm('Contacts', new ContactsForm());
}


}


I also have an actions.class.php for my module that deals with saving the information once it has been passed validation.


class registerActions extends sfActions
{
/**
* Executes index action
*
* @param sfRequest $request A request object
*/
public function executeIndex(sfWebRequest $request)
{
$this->form = new RegisterForm();
if($request->isMethod('post'))
{
$this->form->bind($request->getParameter('sf_guard_user'));
if ($this->form->isValid())
{
$this->form->save();

$this->getUser()->signIn($this->form->getObject());
$this->redirect('@homepage');
}
}
}
}


My problem starts to arise when I enter the new user information into the form via the view, and submit it, it goes through fine but the link table between user and contact is not being updated with that new user's user account to their contact row in the <em>Contacts</em> table. I was wondering how I would go about updating that link table on save and if anyone has example code for me that would be awesome.

Thanks.

Answers (4)

2010-07-22

mongabure ibes answers:

In your RegisterForm.class.php you have to overwrite the doSave() method. I tried it.

public function doSave($con = null)
{
// save the sfGuardUser and the Contact
parent::doSave($con);

//now you can create the link between Contact and sfGuardUser.
$profile = new Profiles();
$profile->setsfGuardUserId($this->getObject()->getId());
$profile->setContactId($this->embeddedForms['Contacts']->getObject()->getId());
$profile->save();

}

2010-07-21

Jakub Zalas answers:

The problem is that your foreign key is in Profiles so Contacts form doesn't know anything about it. Profiles is saved first so it doesn't get Contacts' id.

Contacts object needs to be saved first and the id should be passed to Profiles.

I'd try code below. Note that I didn't test it.


public function doSave($con = null)
{
$this->saveContactsForm($con);

parent::doSave($con);
}

private function saveContactsForm($con = null)
{
$forms = $this->getEmbeddedForms();

if (isset($forms['Contacts']))
{
$form = $forms['Contacts'];
$contacts = $form->getObject()
$contacts->save($con);
$this->getObject()->setContacts($contacts);
}
}


2010-07-22

Loban Rahman answers:

Both the answers above are right. The reason that your link table is not being updated is because without a Profile form, doctrine/symfony does not realize that the GuardUser and Contact are actually related. So you have to create and save the Profile object manually in the doSave method.

However, I must question your data model. You have
GuardUser <--1-------1--> Profile <--1-------1--> Contact
where Profile contains nothing but a foreign key to each of GuardUser and Contact. Why not just have
GuardUser <--1-------1--> Contact.
In fact, you could have just extended the GuardUser model (in the schema file) to include all the fields in Contact. That's a reduction of two tables (so no joins necessary), and no embedded forms needed either.

Of course, perhaps you plan to actually have more fields in Profile, and you just haven't included them yet. Even then, the link table still seems unnecessary unless you have a many-to-many relation somewhere.

Anyway, maybe I'm just trying to steal away the $5 from the good gentlemen above. :-P It's just that I always strive for the correct solution to the entire scenario, rather than just the problem originally posed. :-P

2010-07-22

Damian Martinelli answers:

I'm with Loban Rahman. I think that the table Profile is not needed here.