Retrieve the previous object linked to a form in Symfony 2 - forms

I have a form to edit an address for an user (I pass an entity address to the form). When I modify the address and submit the form, I would like desactivate (with a setActive function) the entity that I passed (without new values) and create a new line with new values. Is it possible ?
Example :
$em = $this->getDoctrine()->getManager();
$client_adr = $em->getRepository('EcommerceBundle:ClientAdresse')->find($id_adr); // here it's the entity that i want disable
$form = $this->createFormBuilder($client_adr)
->add('prenom', TextType::class)
->add('nom', TextType::class)
->add('adresse', TextType::class)
->add('lieu_dit', TextType::class)
->add('complement', TextType::class)
->add('code_porte', TextType::class)
->add('cp', TextType::class)
->add('pays', TextType::class)
->add('save', SubmitType::class, array('label' => 'Modifier'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$adr = $form->getData(); // here it's the entity with new values
$em->persist($new_adr);
$em->flush();
}
In this example, if I modify the name of my entity, I want that my object "$client_adr" keep its previous values and be disabled (if i call setActive by example) and I want that my object $new_adr be saved on a new line in database with modified values.
Thanks

Simple. Right after finding your object but before setting in form, clone your object then set the id null. You may have to add a setId method in your entity class.
$client_adr = $em->getRepository('EcommerceBundle:ClientAdresse')->find($id_adr);
$clone_adr = clone $client_adr;
$clone_adr->setId(null);
$client_adr->setIsActive(false);
$form = $this->createFormBuilder($clone_adr) ...
....
$em->persist($client_adr); // save old, inactive
$em->persist($new_adr); // save new.
$em->flush();

Related

Symfony Forms - Datatime Add +30minutes

When I set beginAt(DateTime) in Forms I would like set the same date in the "endAt" but +30 minutes. I have no clu how to do this :(
The first code is the part Form in my project and the second code is function "new Appointment" to add appointment.
$builder
->add('title', TextType::class, ['label'=>'Tytuł'])
->add('description', TextType::class, ['label'=>'Treść'])
->add('beginAt')
->add('endAt')
;
public function new(Request $request, $id, TokenStorageInterface $tokenStorage): Response
{
$currentUser = $tokenStorage->getToken()
->getUser();
$username = $currentUser->getUsername();
$appointment = new Appointments();
$appointment->setDoctor($id);
$appointment->setUsername($username);
$form = $this->createForm(AppointmentsType::class, $appointment);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($appointment);
$em->flush();
return $this->redirectToRoute('przychodnia_index');
}
return $this->render('appointments/new.html.twig', [
'appointment' => $appointment,
'form' => $form->createView(),
]);
}
Try to use Symfony Form Events to update endAt field on submit for example and use some ajax to submit your form dynamically. There is a great tutorial here (in French sorry) https://www.grafikart.fr/tutoriels/champs-imbriques-888

Insert same entity three times from one form

I'm using symfony4 and In my project I have and entity Bill and it offer two packs:
1) First pack, user can generate just one bill in PDF after filling out a form and saving data in database and it has its own price.
2) Second pack, user can generate Three bills in PDF after filling out a form and saving data in database and this has its own price also.
The first pack is simple and it works fine , I have created BillType and an action in the controller and everything is well.
public function newBillFirstPack(Request $request)
{
$entity = new Bill();
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(BillType::class, $entity);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$em->persist($entity);
$em->flush();
//...............
}
}
return $this->render('frontOffice/bill/new_first_pack.html.twig', array(
'form' => $form->createView()
));
}
The problem is with the second pack , I'd like to know how can I create three bills from one form. I tried to create 3 FormType
- FirstBillType and a twig to render its view.
- SecondtBillType and a twig to render its view.
- ThirdBillType and a twig to render its view also.
And in the controller I created three forms.
I didn't test it yet but even it works I don't like it , I fell it's not a clean solution. Imagine if a day I want to edit an attribute in the formType, so I must edit it in three formsType and three html.twig views, same thing if I want to remove or add an attribute in the forms.
I have see in the documentation "How to Embed a Collection of Forms", but that example is how to embed one attribute many times.
Any good solution ?
If I understand what you need. New action can handle this and depending on your needs form can run different action.
public function newBillThirdPack(Request $request)
{
$entity = new Bill();
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(BillType::class, $entity);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$em->persist($entity);
$em->persist(clone $entity);
$em->persist(clone $entity);
$em->flush();
//...............
}
}
return $this->render('frontOffice/bill/new_third_pack.html.twig', array(
'form' => $form->createView()
));
}

Use the same entity form but two times in Symfony 2

I would like to use the same entity form but two times (to modify two differents properties of my entity). By example, I have a entity User, I create a form to modify the name and another to modify the first name on the same page (just an idiot example). If I submit the first form, it said me that I have extra fields (that is normal). I tried to change the action of the second form with setAction by example but i don't know how to retrieve the form in my controller action.
I started with this code :
$form = $this->createFormBuilder($user)
->add('name', TextareaType::class, array("required" => false))
->add('save', SubmitType::class, array('label' =>'Enregistrer'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return $this->redirectToRoute('myroute');
}
$form2 = $this->createFormBuilder($user)
->add('fname', TextareaType::class, array("required" => false))
->add('save', SubmitType::class, array('label' =>'Enregistrer'))
->getForm();

Symfony: call form handleRequest but avoid entity persist

I have an entity that models a search form and a form type, I use that form for searching purposes only and I don't want that entity to be modified in database, so, when I do this:
$formModelEntity = $em->getRepository('AppBundle:SearchForm')
->findOneBy(array('name' => 'the_model'));
$formModelForm = $this->createForm(new SearchFormType(), $formModelEntity, array('action' => $this->generateUrl('dosearch'), 'method' => 'POST'));
$formModelForm->handleRequest($request); //or ->submit($request);
if ($formModelForm->isValid())
{
$formInstanceEntity->setFieldsFromModel($formModelEntity);
$em->persist($formInstanceEntity);
$em->flush();
}
The $formModelEntity changes are persisted to database, I want to avoid this but still want to take advantage of handleRequest ability to update the entity with all POST values (for read only purposes).
Is this possible?
In symfony, you only have to persist a new entity. If you update an existing entity found by your entity manager and then flush, your entity will be updated in database even if you didn't persist it.
Edit : you can detach an entity from the entity manager before flushing it using this line of code :
$em->detach($formModelEntity);
the method handleRequest Does not save the changes. it only updates the object within your method.
public function newAction(Request $request)
{
// just setup a fresh $task object (remove the dummy data)
$task = new Task();
$form = $this->createFormBuilder($task)
->add('task', TextType::class)
->add('dueDate', DateType::class)
->add('save', SubmitType::class, array('label' => 'Create Task'))
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
// ... perform some action, such as saving the task to the database
return $this->redirectToRoute('task_success');
}
return $this->render('default/new.html.twig', array(
'form' => $form->createView(),
));
}
the following snippet exists at http://symfony.com/doc/current/book/forms.html
and as you can see the entity is not persisted.
You're are probably adding a persist/flush and that's what's causing the entities to be updated.

How to set as a default value in a Symfony 2 form field the authentified username from the FOSUserBundle

i find this snippet useful indeed to put a default value in my form while creating it
$builder
->add('myfield', 'text', array(
'label' => 'Field',
'data' => 'Default value'))
;
what if i want to replace 'default value' with an authentified person from the FOSUser bundle? ( that return true to is_granted("IS_AUTHENTICATED_REMEMBERED"))
i can retrieve that name on a twig file with
{{ app.user.username }}
i have also done it in a controller method with
$username=$this->container->get('security.context')->getToken()->getUser()->getUsername()
but i can't manage to make this working in my form!
i am not sure i understand that container thing well ...neither how to transfer variables betweenn classes and controller...
something around this maybe??
->add('myfield', 'text', array(
'label' => 'Field',
'data' => FOS\UserBundle\Model::$this->getUsername()))
You can passe variable from your controller to your form :
in your controller :
$username=$this->container->get('security.context')->getToken()->getUser()->getUsername()
$form = $this->createForm(new MyFormType($username), $entity);
in your form :
protected $username;
public function __construct (array $username = null)
{
$this->username = $username ;
}
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('myfield', 'text', array(
'label' => 'Field',
'data' => $this->username))
}
Another way to set default values into a form is to set them on the underlying data object for the form, as in this example from the Symfony documentation on building a form:
public function newAction()
{
// create a task and give it some dummy data for this example
$task = new Task();
$task->setTask('Write a blog post');
$task->setDueDate(new \DateTime('tomorrow'));
$form = $this->createFormBuilder($task)
->add('task', 'text')
->add('dueDate', 'date')
->getForm();
return $this->render('AcmeTaskBundle:Default:new.html.twig', array(
'form' => $form->createView(),
));
}
In this example, the form's underlying data object is a Task and the values set on the task are the default values to be displayed in the form. The task object is not persistent. This approach works just as well with a form class and assuming the underlying object for your form is a User would look something like this:
$username = $this->container->get('security.context')->getToken()->getUser()->getUsername();
$user = new User();
$user->setUsername($username);
// could set any other default values on user here
$form = $this->createForm(new MyFormClass(), $user);
The disadvantage of this approach is if the form is used in many places requiring the same defaults the code would be repeated. This is not a situation I've come across so far - my User forms are re-used for create/edit but edit doesn't require the defaults.