Edit entity part with form - php

I have an entity (about 20/25 fields) and i want to edit it with a form.
I just want to edit (and display) few form field.
The problem is, all fields displayed are correctly update, but fields that are not rendered are update with "null" value by default.
My controller :
$em = $this->getDoctrine()->getManager();
$LaboRequest= $em->getRepository('MyBundle:LaboRequest')->find($id);
$form = $this->createForm('MyBundle\Form\LaboRequestType', $LaboRequest);
if ($request->isMethod('POST') && $form->handleRequest($request)->isSubmitted() && $form->isValid()) {
$em->persist($LaboRequest);
$em->flush();
return $this->redirectToRoute(...);
}
return $this->render('...', array(
'LaboRequest' => $LaboRequest,
'form' => $form->createView(),
));
I only render few fields in my view, so i can understand, by default symfony use "null" for fields that are not render.
But is there a way to edit a part of an entity and not affect data of the entity with "null" value ?

I'm not sure you can do that.
But you can extend your original form and call
$builder->remove('xxx')
for each field you want to remove

Related

Symfony 5 - Get old collection data before submit form

In my symfony 5 project I would like when submitting a certain form, compare the entity before and after submission.
So keep a copy of the original entity in order to perform processing.
I've :
$parametresAdmin = $entrepriseService->getParametresAdmin();
$form = $this->createForm(ParametresAdminType::class, $parametresAdmin, [
'entreprise' => $this->getUser()->getEntreprise(),
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entrepriseService->updateParametres($parametresAdmin);
return $this->redirectToRoute('admin_parametres');
}
In fact, I want to get a copie of $parametresAdmin->getTypesConges() (which is a collection on OneToMany).
So, when the form is submitted, I want compare the old $parametresAdmin->getTypesConges() and the new $parametresAdmin->getTypesConges().
The "$parametresAdmin->getTypesConges()" part looks like this:
I can add / modify leave types on the fly. Except that I do not want to authorize the possibility of modifying the "Balance type" field for the types of leave that already exist. There is just for those that I add that I leave the possibility in the ChoiceType. So on the front side, it's good. But on the back side, no.
But it doesn't work
What I do :
I change the "Solde initial" for the first line :
But when I submit, I've the same value (the new value : 10 )
EDIT : Currently, I've now :
$parametresAdmin = $entrepriseService->getParametresAdmin();
$typeConges = $parametresAdmin->getTypesConges();
$oldTypesConges = clone $typeConges;
$form = $this->createForm(ParametresAdminType::class, $parametresAdmin, [
'entreprise' => $this->getUser()->getEntreprise(),
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$typeConges = $parametresAdmin->getTypesConges(); // update with new data
dd($oldTypesConges, $parametresAdmin->getTypesConges());
$entrepriseService->updateParametres($parametresAdmin);
return $this->redirectToRoute('admin_parametres');
}
You should clone your data like this :
$typeConges = $parametresAdmin->getTypesConges();
$oldTypeConges = clone $typeConges;
// handleRequest(), isValid(), isSubmit() ...
$typeConges = $parametresAdmin->getTypesConges(); // update with new data
dd(oldTypeConges, $parametresAdmin->getTypesConges());
phpdoc says about :
When an object is cloned, PHP will perform a shallow copy of all of the object's properties. Any properties that are references to other variables will remain references.
Take a look at this question on stackoverflow.
Use session variables to store the old data:
To store your data before rendering the form in the controller, use:
$this->get('session')->set('oldTypesConges ', $typesConges );
And after submitting, read the data stored to compare it with the new one:
$oldTypesConges = $this->get('session')->get('oldTypesConges ');
Now, you can compare $typesConges and $oldTypesConges.
This solution was inspired from here: How to set session variables for all the controllers in Symfony2?
$versionsBeforeSubmit = [];
foreach($produit->getVersions()->getIterator() as $version) {
$versionsBeforeSubmit[] = clone $version;
}
$form->handleRequest($request);
if($form->isValid() && !$hasError) {
dump($versionsBeforeSubmit);
}

Symfony 2 Entity Field Type not selecting existing data in edit action

I have an entity field type I'm using in an 'edit' form.
The field type lists the correct options and the data persists, but it selects the 'top' result in the list by default, and not the data that is in the DB.
So for example if I have a record with the shelf marked as SH6, and I go to edit, the default shelf selected in the entity field type will be whatever is at the top of the list, ie SH1.
This means that users might go to edit unitsInStock and accidentally change the shelf value, because they didn't realise it was set to the wrong thing. Even more annoying is that even if you know about the problem, you may not remember the value it is supposed to be set to.
This is my controller action.
public function editAction($id, Request $request) {
$em = $this->getDoctrine()->getManager();
$article20000stock = $em->getRepository('RegenerysQMSBundle:Article20000Stock')->find($id);
if (!$article20000stock) {
throw $this->createNotFoundException(
'No id ' . $id
);
}
$form = $this->createFormBuilder($article20000stock)
->add('article20000Information')
->add('unitsInStock')
->add('expiryDate')
->add('shelf', 'entity', array('class' => 'RegenerysQMSBundle:Shelf', 'property' => 'id', ))
->add('submit', 'submit')
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
$em->flush();
return $this->redirectToRoute('regenerys_qms_article20000stock_individual', array('id' => $id));
}
$build['form'] = $form->createView();
return $this->render('forms/editArticle20000Stock.html.twig', $build);
}
So the Entity was lacking a relationship, which is what was causing the issue.

Validation of a form before submission

Using Symfony, version 2.3 and more recent, I want the user to click on a link to go to the edition page of an already existing entity and that the form which is displayed to be already validated, with each error associated to its corresponding field, i.e. I want
the form to be validated before the form is submitted.
I followed this entry of the cookbook :
$form = $this->container->get('form.factory')->create(new MyEntityFormType, $myEntity, array('validation_groups' => 'my_validation_group'));
$form->submit($request->request->get($form->getName()));
if ($form->isValid()) {
...
}
But the form is not populated with the entity datas : all fields are empty. I tried to replace $request->request->get($form->getName()) with $myEntity, but it triggered an exception :
$myEntity cannot be used as an array in Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php
Does anyone know a method to feed the submit method with properly formatted datas so I can achieve my goal ? Note : I don't want Javascript to be involved.
In place of:
$form->submit($request->request->get($form->getName()));
Try:
$form->submit(array(), false);
You need to bind the the request to the form in order to fill the form with the submitted values, by using: $form->bind($request);
Here is a detailed explanation of what your code should look like:
//Create the form (you can directly use the method createForm() in your controller, it's a shortcut to $this->get('form.factory')->create() )
$form = $this->createForm(new MyEntityFormType, $myEntity, array('validation_groups' => 'my_validation_group'));
// Perform validation if post has been submitted (i.e. detection of HTTP POST method)
if($request->isMethod('POST')){
// Bind the request to the form
$form->bind($request);
// Check if form is valid
if($form->isValid()){
// ... do your magic ...
}
}
// Generate your page with the form inside
return $this->render('YourBundle:yourview.html.twig', array('form' => $form->createView() ) );

Make changing form (like draft/finish) on symfony2

I want to make forms
which has three scenes
1.input view (which has 'confirm' button)
2.draft check view (which has 'send' button)
3.send view
in method 1 you can input the data then click 'confirm' button
the system write the data in DB as draft.
in method 2 you see the data and confirm then push 'send' button
the system write the flg 'confirmed'
these are my code.
it works well method 1 but if I push 'send' button in method2.
it doesn't go.
if ($form->isValid()) {
My idea is something wrong??
public function writeEvalStudentAction(Request $request,$keyStr){
...
$form = $this->createFormBuilder($evalStudent)
->add('commentToStudent')
->add('confirm','submit')->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
if ($form->has('send')){
if ($form->get('send')->isClicked()){
//set confirm flg then shows thanks screen.
$evalStudent->setConfirmed(true);
$em->persist($evalStudent);
$em->flush();
return $this->render('AcmeMemberBundle:Default:confirmedEvalStudent.html.twig');
}
}
if ($form->has('confirm')){
if ($form->get('confirm')->isClicked()){
// write in the db as draft.
$evalStudent->setCommentToStudent($form->get('commentToStudent')->getData());
$em->persist($evalStudent);
$em->flush();
$form = $this->createFormBuilder($evalStudent)->add('send','submit')->getForm();
return $this->render('AcmeMemberBundle:Default:checkEvalStudent.html.twig',
array('form' => $form->createView()));
}
}
return $this->render('AcmeMemberBundle:Default:writeEvalStudent.html.twig',
array('form' => $form->createView()));
}
Split it up in 4 controller actions with 4 separate routes. Whereas route2 and route3 require the id of your draft object in the routing parameters.
Make the form1 from step 1 point to step2.
In step2 validate the form and if it is ok insert to db and get your id, then show form2 which points to step 3, if not show form1 with form errors.
Same for step2->step3 and step3->step4.
In step 4 you convert your draft to a final object and persist it and remove the draft.

Symfony2 Saving data of related Entity after submiting form

I'm starting developing with Symfony2 and looks like I need help. I have Product entity related with SynchronizationSetting entity. I can edit product data by form maped with his entity. But I also need to modify some data related to product in SynchronizationSetting. To do that I've modified the form so it look like that (Vendor\ProductBundle\Form\ProductType.php):
...
->add('synchronization_setting', 'choice', array(
'choices' => array('daily' => 'Daily', 'weekly' => 'Weekly', 'never' => 'Never'))
After form is submitted selected checkbox values are passed to setSynchronizationSetting method in Product Entity. Then I do that (Vendor\ProductBundle\Entity\SynchronizationSetting.php):
public function setSynchronizationSetting($data)
{
$synchronizationSetting = new SynchronizationSetting();
$synchronizationSetting->setDaily(in_array('daily', $data) ? '1' : '0');
...
}
And now I need to somehow save those SynchronizationSetting entity into database. I read that calling entity manager from here is very bad practice so... how should I save this?
One possible way (I'm not sure if it's good practice)
public function setSynchronizationSetting($data)
{
$synchronizationSetting = new SynchronizationSetting();
$synchronizationSetting->setDaily(in_array('daily', $data) ? '1' : '0');
}
public function retSynchronizationSetting()
{
return $this->synchronizationSetting;
}
Then in your controller in place where you handle form data you call retSynchronizationSetting() and save entity using EntityManager.

Categories