How to map two entities in the one Symfony Form - forms

The problem I am having now is related to entities and forms in Symfony2.
While creating the form that refers to one entity I can simply wire it by saying:
$user = new User();
$form->createForm(new UserType(), $user);
...
$manager->persist($user);
$manager->flush();
And that is working fine. But the problem raises when I have more complex form that is built based on other forms, e.g.
So, let's imagine I have a form called RegistrationType that contains two other forms called UserType wired to User entity and ProfileType wired to Profile entity.
Now, how can I handle that in the controller? I mean, I cannot do something like:
$user = new User();
$profile = new Profile();
$form->createForm(new RegisterType(), $user, $profile);
OR
$form->createForm(new RegisterType(), [$user, $profile]);
...
$manager->persist($user);
$manager->flush();
$profile->setUserId($user->getId());
$manager->persist($profile);
$manager->flush();
If I pass only $user, like so
$form->createForm(new RegisterType(), $user);
Symfony will complain that there are properties that are not mapped, of course I can set them to 'mapped' => false but then I have to set them later on manually.
What's the best way to handle this?
Thanks in advance!

Create UserType, ProfileType and RegistrationType forms. RegistrationType should add UserType and ProfileType as its children. Create Registration DTO and set it as data_class for RegistrationType. Then you can write something like
$user = new User();
$profile = new Profile();
$form->createForm(new RegistrationType(),
new Registration($user, $profile));

Related

Submitted Symfony form return wrong field value

I am doing some tests with Symfony 4 Forms and the answer to my question might be very simple but I am really confused right now and I need fresh eye to understand the following strange behavior.
Here is the context : I have a page /edit which handle a form for an entity named Promoter in a very classic way but after passing the validation I am generating and setting a randon firstname then flush the entity (which is updated with the new data form the form and the new firstname), and after instead of redirecting to another page, I return to the same page with the new Promoter entity.
My expectation is the see the new generated firstname but in fact it shows the old one(the one send by the form to the controller) and I cannot understand why? Can somebody has a clue?
I should add that data in db are correctly updated.
The Controller code is:
/**
* #Route("/{id}/edit", name="promoter_edit", methods={"GET","POST"})
* #param Request $request
* #param Promoter $promoter
* #return Response
*/
public function editAction(Request $request, Promoter $promoter): Response
{
$form = $this->createForm(PromoterFormType::class, $promoter);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$firstname = substr(str_shuffle('abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ'),0,5);
$promoter->setFirstname( $firstname );
$this->getDoctrine()->getManager()->persist($promoter);
$this->getDoctrine()->getManager()->flush();
}
return $this->render('promoter/edit.html.twig', [
'promoter' => $promoter,
'form' => $form->createView(),
]);
}
Thanks
It seems to me that when you post your form, you create the new one before updating your 'promoter'. You should try to reload your page after submitting your form.
if ($form->isSubmitted() && $form->isValid()) {
$firstname = substr(str_shuffle('abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ'),0,5);
$promoter->setFirstname( $firstname );
$this->getDoctrine()->getManager()->persist($promoter);
$this->getDoctrine()->getManager()->flush();
return $this->redirect($request->getUri());
}
Does your PromoterFormType class have a field for firstname? Because otherwise it could override your newly set Firstname.
If so fix:
In PromoterFormType
->add('firstname')
needs the option: 'mapped' => false.
Or simple delete it from the formType.
More info
If not can you show us the FormType and the Promoter Entity?
Hope this helps for you!

Symfony3 - how to compare properties from 2 different entities

I want to create a view where an event is displayed only if it is owned by the currently logged in user.
So I want to compare LoginID from the Events entity to the current user ID.
I tried with the following function:
public function showAction(Events $event, $id)
{
$em = $this->getDoctrine()->getManager();
$user=$this->getUser()->getLoginid();
$guests = $em->getRepository('VendorMyBundle:Guests')->findByEventid($id);
$events = $em->getRepository('VendorMyBundle:Events')->findByEventid($id);
// condition to display only events owned by the current user
if ($events->getLoginid()==$user){
$session = new Session();
$session->set('eventid', $id);
$deleteForm = $this->createDeleteForm($event);
return $this->render('events/show.html.twig', array(
'event' => $event,
'delete_form' => $deleteForm->createView(),
'guests' => $guests,
));
}
$this->addFlash('error', 'The event does not exist or you do not have permission to view it.');
return $this->redirectToRoute('home_page');
}
LoginID in Events entity is a Many-to-One relation property towards the Logins entity which is my user provider entity.
When I try to view with that method in my controller I get this: Error: Call to a member function getLoginid() on a non-object on the line with the IF statement.
Additional question would be, how do I compare 2 property values from 2 different entities?
Since the problem is that you are returning an array you have two choices, update the findByEventid() to return a single result
return $query->getSingleResult();
or
if ($events[0]->getLoginid()==$user){
..
}
Hope this help you.

Symfony2 Form Dropping Entity Data

This questions is NOT about how to embed an entity that is simple and straightforward my question is about an abnormality I am seeing and can't reconcile.
I have an Entity (Contact) I have an "Email" relation on this and want to have the ability to embed Emails in my create new method.
So I do the usual embed steps:
1) Add my collection to my form (contactType.php)
->add('emails', 'collection', array(
'type' => new EmailType()
))
2) In the Controller I add a new empty Email entity and set that as my default data for my form
$entity = new Contact();
$email = new Email();
$entity->addEmail($email);
$form->createForm(new ContactType(), $entity);
This is where the issue occurs, going into "createForm" my $entity has a collection called Emails, coming out the $form is a blank ContactType, no Email attached to it... it's as if the defaultData is just being ignored.
If you have seen this or have any idea why this would happen I would love some input.
We have modified our getter to return an Associative Array and this seems to break the Form builder, The following breaks the Form Builder:
public function getContacts()
{
$array = new ArrayCollection();
$property = (is_array($this->contacts)) ? $this->contacts : $array;
foreach($property as $entity)
{
$array[$entity->getType()->getName()] = $entity;
}
return $array;
}
the basic getter is just
return $this->contacts;
Which works, it seems ArrayCollection() isn't a simple Associative Array as we assumed it could be.

ZF2 layout form set input filters and validation

For my application in Zend Framework 2 I created a 'search form' in my layout.phtml.
I did this in my Application module by adding the search form as an variable.
(Form location Application/src/Application/Form/SearchForm.php)
Application/Module.php:
public function setFormToView($e)
{
$searchForm = new SearchForm();
$viewModel = $e->getViewModel();
$viewModel->setVariables(array(
'searchForm' => $searchForm,
));
}
The form directs to an Action in another module, here I want to handle what to do with
the incoming query.
MyModule/src/MyModule/Controller/MyModuleController.php
public function dataAction()
{
$form = new SearchForm();
$form->get('submit')->setValue('Add');
$website = $this->params()->fromQuery('search');
return array('searchForm', $form);
}
Getting the query 'search' is no problem, it works well. No I want to use my inputFilter I created under 'Application/src/Application/Model/Search.php'.
I tried to add this in my 'dataAction()' but no results, but I even can't change the submit value as I tried in my example above.
How do I set this in the right way in this situation? Or else, what is the right situation to handle a search form in layout.phtml.
Thanks in advance,
Nick

Symfony: How to hide form fields from display and then set values for them in the action class

I am fairly new to symfony and I have 2 fields relating to my table "Pages"; created_by and updated_by. These are related to the users table (sfGuardUser) as foreign keys. I want these to be hidden from the edit/new forms so I have set up the generator.yml file to not display these fields:
form:
display:
General: [name, template_id]
Meta: [meta_title, meta_description, meta_keywords]
Now I need to set the fields on the save. I have been searching for how to do this all day and tried a hundred methods. The method I have got working is this, in the actions class:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form_params = $request->getParameter($form->getName());
$form_params['updated_by'] = $this->getUser()->getGuardUser()->getId();
if ($form->getObject()->isNew()) $form_params['created_by'] = $this->getUser()->getGuardUser()->getId();
$form->bind($form_params, $request->getFiles($form->getName()));
So this works. But I get the feeling that ideally I shouldnt be modifying the web request, but instead modifying the form/object directly. However I havent had any success with things like:
$form->getObject()->setUpdatedBy($this->getUser()->getGuardUser());
If anyone could offer any advice on the best ways about solving this type of problem I would be very grateful.
Thanks,
Tom
After processing and saving the form you could set those fields on the object and re-save:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form->bind($request->getParameter($form->getName()));
if ($form->isValid())
{
$page = $form->save();
$user = $this->getUser()->getGuardUser();
$page->setUpdatedBy($user);
if (empty($page->created_by))
{
$page->setCreatedBy($user);
}
$page->save();
$this->getUser()->setFlash('notice', 'Successfully saved page.');
$this->redirect('#homepage');
}
}
There's also a Doctrine extension called Blameable that automatically sets edited_by and created_by fields on specified models. The Doctrine website is undergoing some reorganization but here is the cached page for the extension.
To process your form create a new object, set the fields then save.
$article = new Article();
$article->setName($request->getParameter($form->getName());
$article->setDescription($request->getParameter($form->getDescription());
$article->setMetaKeywords($request->getParameter($form->getMetaKeywords());
$article->save();
What you want to do is customize your form and unset the 'created_at' and 'updated_at' pieces of the form in configure
class SampleForm extends BaseSampleForm
{
public function configure()
{
unset(
$this['created_at'],
$this['updated_at']
);
}
}
Then they won't show up in the form and will get the values setup by the "Timestampable" behavior before being saved
http://stereointeractive.com/blog/2010/04/07/symfony-forms-hide-created_at-updated_at-columns/