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

How to populate sfApplyApply Form to edit profile? Symfony


I'm using the sfForkedDoctrineApplyPlugin. I want users to be able to edit their profile: username, email, password, firstname, lastname, etc. What's the best way to do this without rewriting a lot of code? The module that that requires this functionality is not a backend module.

Right now I can generate the form in the action like so:
$this->form = new sfApplyApplyForm();

But, how do I pre-fill it with the user's info and make the form update the user without rewriting the plugin code.

I tried: $this->form->setUsername($username) , etc, but the form doesn't have setters.

I can use setDefault in the configure method for the form, but then I would have to duplicate the code and create an entirely new form class.

I would like to do something like this, if possible in my module:

$user = $this->getUser()->getGuardUser()->getProfile();
$userGuard = $this->getUser()->getGuardUser();
$this->form = new sfApplyApplyForm($user) //index action to show pre-populated form:

//populate sfApplyApply form with relevant info from user object

Answers (1)


Loban Rahman answers:

First, lets make some assumptions. (If the assumptions are slightly inaccurate, correct them in a comment and I will adjust my answer).

sfDoctrineGuardPlugin provides you with the sfGuardUser model class, and you've named your profile model class sfGuardUserProfile (which is the default). The former class has the username, and password, while the latter class has the firstname, lastname, email, etc.

Now to answer the question:

Note that with just the sfDoctrineGuardPlugin, you already have sfGuardUserForm and sfGuardUserProfileForm classes, which you can use to edit the relevant fields in each class. There is also a sfGuardUserAdminForm, which extends the sfGuardUserForm and adds an extra widget for the password (so you have to enter password twice).

The sfForkedDoctrineApplyPlugin offers you extra forms for (1) having new users register, with email confirmation, and (2) having users send password reset requests, with email confirmation.

According to your question, you don't actually need the sfApplyApplyForm, which is to register new users only. You just need the sfGuardUserAdminForm and sfGuardUserProfileForm. If you want the user to be able to change both your guard user and user profile fields in one go, then you need to embed the profile form into the guard user form. Like so:

$userGuard = $this->getUser()->getGuardUser();
$userProfile = $userGuard->getProfile();

$userGuardForm = new sfGuardUserAdminForm($userGuard);
$userProfileForm = new sfGuardUserProfileForm($userProfile);

$userGuardForm->embedForm('Profile', $userProfileForm);

Then echo $userGuardForm in your template, or customize the output.

atentaten comments:

Your assumptions are correct about the plugins and embedding the UserProfileForm and the UserGuardForm will definitely work.

My initial thought was that since the sfApplyApplyForm had all the fields I needed, I could try to reuse it to edit the profile, but I now see that it's less cumbersome to just embed the forms as you mentioned.

Now the question of pre-prepopulating and customizing the embedded form is at hand. Is the best approach to:

1. add logic in the 2 form classes to receive UserGuard and UserProfile objects, then remove widgets, and set default values based on these injected objects.

2. remove unwanted widgets and set default values in the action.

3. create new form classes that inherit from UserGuard and UserProfile and apply number 1?

Loban Rahman comments:

It's mostly a matter of taste, actually. My personal preference is to change the form classes only if these changes are universal to all possible use-cases of the form (and any that may extend from it). For example setting specific labels, unsetting created_at and updated_at fields, etc. If I'm making a customized version of a form specifically for one module, then i would inherit from that form class in the lib/form directory of that module. Later if I find that the customizations are useful elsewhere, I move the class back into the main lib/form directory, and possibly even move the customization back into the main form class.

In this case, I would create a new class that inherits from UserGuardForm. In the configure function, I would customize as necessary, instantiate a UserProfile form, customize that, and embed into itself. Hence, your code would be

class CustomUserForm extends sfDoctrineGuardUseForm {
public function configure() {
// Customize the guard user form
$profile = $this->getObject()->getProfile();
$profileForm = new sfGuardUserProfileForm($profile);
// Customize the profile form
$this->embedForm('Profile', $profileForm);

And in your action:

$userForm = new CustomUserForm($this->getUser()->getGuardUser());

PS. I never advocate method #2.

atentaten comments:


Your answers are well crafted and I appreciate your time.