Multiple Profile forms with FOSUserBundle - php

I'm creating an application with Symfony 2 and the FOSUserBundle. I have my own UserBundle configured correctly. My User Entity has a lot of attributes of different categories (For example location settings, personal settings, ...) so I want to make different forms for each category so I can show each setting category on a different page.
I know how to make a custom profile form (it's in the FOSUserBundle Documentation), I already made multiple FormTypes and an additional controller but I just can't get it populated with the current user data. I tried the following
$user = $this->container->get('security.context')->getToken()->getUser();
// Try 1
$form = $this->createForm(new InnerCharacteristicsType());
// Try 2
$form = $this->createForm(new InnerCharacteristicsType($user));
// Try 3
$form = $this->createForm(new InnerCharacteristicsType(), $user);
// Try 4
$form = $this->createForm(new InnerCharacteristicsType(), array('user' => $user);
return $this->render('AcmeUserBundle:EditProfile:inner.html.twig', array('form' => $form->createView()));
(Of course, I didn't try them at the same time)
I also tried to make the new forms a service by adding my InnerCharacteristics Form to the services.yml but I couldn't find any documentation on this. The profile.xml in the FOSUserBundle itself also isn't very helpful because I couldn't find where the parameters are pointing at. Also the XML to YAML conversion isn't very easy since the documentation about this is not very helpful (this is needed because the FOSUserBundle configuration is in XML and my UserBundle configuration in YAML).
This is what i have in my services.yml now:
acme_user.inner_characteristics_profile.form:
class: Symfony\Component\Form\Form
factory_service: form.factory
factory_method: createNamed
I hope someone can give me some pointers where to go next.

This is the correct way to create the form:
$form = $this->createForm(new InnerCharacteristicsType(), $user);
Inside your form you should do something like this:
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Add fields
$builder->add('name', 'text', array('label' => 'Name:'));
}
This should load up the name property from the user object inside your form. Is the form successfully loaded?

Related

Twig and controller in Symfony

I have a form made in Twig and I want to pass the values of this form to my database, so how do I pass the Twig values to the controller?
In the first photo is the form that I created in twig
Formulario twing
In the second picture is the controller (the entities, and the connection with the database with doctrine orm is complete too), it is only necessary to know how to take the form data and to pass to the controller
Controller
When form submits you will get a POST request to the same URL that it was built in.
Stick to this tutorial:
http://symfony.com/doc/current/forms.html
If you create a form with html and not symfony form you must manually handle form and other step.
you must submit your form to you controller route that seems is cadastrarAction().
Don't forget to declare route with POST method for cadastrarAction().
In controller you can access posted data from request argument like this.
use Symfony\Component\HttpFoundation\Request;
class FooController extends Controller {
cadastrarAction(Request $request)
{
// Find what you exactly want. if you want to get query use this
$request->getQueryString()
}
}
This is bad practice that declare form manually. you must use FormType for easily handle and persist form to database. use symfony official site for more information about form and entity.
In official documentation you can find flow, how create entity, form, twig template and set data in database.
If you need get data from form use this:
if ($form->isSubmitted() && $form->isValid()) {
// -------- Hear you take data --------
$ideda = $form->get('ideda')->getData();
$email = $form->get('email')->getData();
$telemovel = $form->get('telemovel')->getData();
// ---------- Hear you set data's ---------
$usuario -> setIdeda($ideda);
$usuario -> setEmail ($email );
$usuario -> setTelemovel($telemovel);
}):

Symfony2 tutorial deprecated function

I am learning Symfony2 Framework, and to start things of I found this tutorial: Tutorial. Everything has been going well until I hit this issue:
in Tutorial Part2. In Creating the form in the controller section i discover that the getRequest() function is deprecated and bindRequest() is not found in class.
These two have held me back with the tutorial and learning progress. I there any other way of constructing this controller without using these functions or are there other functions that do exactly the same thing.
See this part of the Symfony Documentation. It shows that you should use handleRequest, like so:
// Top of page:
use Symfony\Component\HttpFoundation\Request;
...
// controller action
public function newAction(Request $request)
{
$form = $this->createFormBuilder()
// ...
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
// perform some action...
return $this->redirect($this->generateUrl('task_success'));
}
return $this->render('AcmeTaskBundle:Default:new.html.twig', array(
'form' => $form->createView(),
));
}
You may also find this link useful: Handling Form Submissions.
The Request as a Controller Argument
Getting the request object in this way might be a little confusing at first, to quote the documentation:
What if you need to read query parameters, grab a request header or
get access to an uploaded file? All of that information is stored in
Symfony's Request object. To get it in your controller, just add it as
an argument and type-hint it with the Request class:
use Symfony\Component\HttpFoundation\Request;
public function indexAction($firstName, $lastName, Request $request)
{
$page = $request->query->get('page', 1);
// ...
}
This information can be found on the Controller Documentation.

Future Proofing Changes to Validation of Username/Password Field in ZFCUser

I've been looking around at how to change the actual validation process of the registration fields in the ZFCUser module in Zend Framework 2.
There is a lot about extending and adding new fields etc. to the form but not validating these fields or extending the existing validation.
I have taken a look inside the code and found the RegistrationForm.php file and added my customer Regular Expression filters.
This works well and as expected but I am worried about this being over-written on any future upgrade.
How would I go about doing this so it is upgrade safe? Is it a case of extending a specific class or adding it as a local file in my custom modules as I have done with the view files.
I've same problem as you, and also do not find proper solution. But IMHO better way than change original source code is to override one of the ZfcUser services.
There is a service called 'zfcuser_change_password_form' defined in zfc-user Module.php. If you create own service with same name - the original one will be overriden. So, first you need to define your own filter / validator class (YourFilter), then in your Module.php add:
public function getServiceConfig()
{
return array(
// ...
'factories' => array(
// ...
'zfcuser_change_password_form' => function ($sm) {
$options = $sm->get('zfcuser_module_options');
$form = new \ZfcUser\Form\ChangePassword(
null, $sm->get('zfcuser_module_options')
);
$form->setInputFilter(
new \YourModule\Form\YourFilter($options)
);
return $form;
},
),
);
}
Such solution allows to update zfcuser without overriding your changes.

How do I make my forms modular in Symfony?

I have 10 forms in a single page (they are in tabbed pages).
My controller function is massive, in an effort to make the forms modular, I was planning to just show the forms in my controller function and do the POST to their correspondent controller.
Some of these 10 forms are used in other pages, so by changing the action url, it makes it easier to manage them all in separate controllers.
But then, how am I going to show the form errors and prevent the form to reset if it was invalid?
I could achieve this if embedded controllers could redirect. Am I missing another option?
Symfony2 has to have a reason not to allow redirects in embedded controllers, but I wonder why.
Third edit:
Images of the actual forms: http://imgur.com/sIx3sgs,tnZkvqM,ZAP950s,hk45oTW#0
Image 1: Step1 (can only be created once)
Image 2: Step5 (can be created multiple times) You can see the create form and the edit form
Image 3: Step5 ui forms are slided up.
Image 4: Step6 same as Step1
These forms are not required to go in order, the user can create and save step6 without ever needing to create step1.
Second edit:
This isn't a multiple step form. I named them Step1, Step2, etc. for convenience.
Edit:
This is what I have:
class DefaultController extends Controller{
public function processAction(){
$request = $this->getRequest();
/*** FORM 1 ****/
$entity = new Step1();
$form1 = $this->createForm(new Step1Type(), $entity);
if ($request->getMethod() == 'POST'){
$form1->bindRequest($request);
if($form1->isValid()){
return $this->redirect($this->generateUrl('some_link'));
}
}
/***/
//Do the same for other forms
return array(
'form1' => $form1->createView()
//[...to form10]
);
}
}
This is what I would like to have: (I would do it with embedded controllers but you can't redirect)
class DefaultController extends Controller{
public function processAction(){
$request = $this->getRequest();
/*** FORM 1 ****/
$entity = new Step1();
$form1 = $this->createForm(new Step1Type(), $entity);
//change $form1 action url to point to Step1Controller->createAction()
/***/
//Do the same for other forms
return array(
'form1' => $form1->createView()
//[...to form10]
);
}
}
class Step1Controller extends Controller{
public function createAction(){
$request = $this->getRequest();
$entity = new Step1();
$form = $this->createForm(new Step1Type(), $entity);
$form->bindRequest($request);
if($form->isValid()){
//save entity
return $this->redirect($this->generateUrl($getRedirectLinkFromForm));
}
return $this->redirect($this->generateUrl('some_other_link'));
}
}
I came up with 4 solutions that I could think of, in order from best to worst:
AJAX
No redirect in embedded controllers
Save in session posted data / form errors in case form is not valid
Modify Symfony2 internals to allow redirect from an embedded controller
AJAX
This is actually the best as it reduces whole page requests and it's highly modular.
You would render all 10 embedded controllers but each submit button will instead do an ajax post pointed to the correspondant controller, which will only process the correspondent forms and it will only return the view of that specific form.
And you don't need to get fancy on your javascript, as you only need to make the AJAX call when submit is clicked and load the response to the div where the form is.
No redirect in embedded controllers
The problem with this is that if the user presses F5, it will resend the POST data.
Save in session posted data / form errors in case form is not valid
and Modify Symfony2 internals to allow redirect from an embedded controller
These 2 options are less desirable as it creates complexity.

Can I change a Form Class action on build?

On a form classe's buildForm method (AbstractType derived) can I set the action of that form?
What I want to do is similar to the setAction method that I can use when building an embedded form:
$form = $this->createFormBuilder()
->setAction($this->generateUrl('my_action'))
->add('field', 'text')
->add('button', 'submit');
I mean, is the setAction an equivalent to form classes?
You get access to the same form builder in the buildForm method, so just calling the setAction on it will work:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->setAction($path);
}
The question is how you pass the $path to your form type. One of the ways would be to pass it as an option when creating the form. But if you're passing the $path anyway, why not just set the action itself?
$form = $this->createForm(new MyType(), $object, array(
'action' => $this->generateUrl('my_action'),
));
Another way would be to inject the router to the form type and use it to generate the URL, but I don't think it's a good idea to make that kind of decisions in a form type.

Categories