0

I have a collection of forms like in the code below, which leads to a form that looks like the following (with two example entries):

Just like this

When clicking submit, the data i provided to the form (builder) instance is updated accordingly.

Problem: The problem i have is, that the list can be quite long, so i need a way of knowing which instances have been updated.

I thought about storing a clone of the original data (here $leadPartnerList in my session. But that does not feel right.

Does symfony (specifically form builder) provide such functionality out of the box? Or what would be an efficient solution to know which fields in the form have been updated and which not?

My Twig:

{% block content %}

<div>

    {{ form_start(form) }}
    {% for partner in lead_partners %}
        {{ form_row(partner.name) }}
    {% endfor %}
    {{ form_end(form) }}

</div>

{% endblock content %}

My Controller Code:

public function overview(Request $request, \App\Utility\LeadPartnerLoader $LeadPartnerLoader)
{
    $leadPartnerList = $leadPartnerLoader->loadAll();
    $formBuilderData = [
        'lead_partners' => $leadPartnerList
    ];

    $listForm = $formFactory->createNamedBuilder('listForm', FormType::class, $formBuilderData)
        ->add('lead_partners', CollectionType::class, [
            'entry_type' => LeadPartnerFormType::class,
            'allow_add' => true
        ])
        ->add('submit', SubmitType::class, [
            'label' => 'Submit Changes'
        ])
        ->getForm();

    ... handleRequest and so on and so forth...
}

And the Form Type (LeadPartnerFormType):

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => LeadPartner::class,
    ));
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('name', TextType::class);
}

$leadPartnerList is of type array with LeadPartner instances within each entry of the array.

PLEASE NOTE: I'm not using Doctrine here!

  • Possible duplicate of [Is there a built-in way to get all of the changed/updated fields in a Doctrine 2 entity](https://stackoverflow.com/questions/9057558/is-there-a-built-in-way-to-get-all-of-the-changed-updated-fields-in-a-doctrine-2) – Fabian Schmick Feb 07 '19 at 13:10
  • @Fabian I'm not using Doctrine. –  Feb 07 '19 at 13:19
  • 1
    If your controller follows the typical flow then you first retrieve the list of entities, pass them to the form and then run the handle request. If you clone the list before handle request then you will have before and after copies to compare. No need for sessions. And while I realize you are not using Doctrine, it might be worth reading about their [change tracking policies](https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/change-tracking-policies.html) just for ideas. Having entities emit an "changed" event might also be an approach to consider. – Cerad Feb 07 '19 at 13:38
  • For some reason I did not see your controller code. Early in the morning here. Just clone $leadPartnerList before calling handle request. No need to store it in the session. And while off topic, passing the $leadPartList as option data is strange. Might want to see the collection example in the docs for a somewhat cleaner approach. – Cerad Feb 07 '19 at 13:57
  • @Cerad It's not option data: createNamedFormBuilder and createFormBuilder have a different interface. Also, just cloning won't work, because the dataset retrieved by `loadAll()` might change between displaying the form and submitting it, thus i'd have a clone of another dataset than that i used to show the form the first time it got submitted. –  Feb 07 '19 at 14:19
  • You are not quite understanding the process. Your controller method get's called twice. Once for a GET to show the user that data and then a second time for the POST when the user submits. So you check for changes inside of the $form->isValid() block. – Cerad Feb 07 '19 at 14:31
  • @Cerad That's what i mean. The second time the controller method get's called is also the second time `$leadPartnerList = $leadPartnerLoader->loadAll();` get's called. And i need the state of `$leadPartnerList` from the first run to compare it to the results the user submitted through the form during the second run (and as you stated the comparison happens within the `$form->isValid()`-block). Did i misunderstood you (or the symfony lifecycle), maybe? –  Feb 07 '19 at 14:43
  • Okay. You are probably looking for [optimistic locking](https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/transactions-and-concurrency.html#optimistic-locking). Each table gets a version column. You set things up such that each update causes the version to increment. You send the version number to the browser as part of your form. When the form submits you compare current database versions with the ones originally sent and take appropriate action if they are different. – Cerad Feb 07 '19 at 15:56

1 Answers1

-1

Use symfony EventListener or EventSubscriber. See: https://symfony.com/doc/current/doctrine/event_listeners_subscribers.html

JessGabriel
  • 1,062
  • 9
  • 18
  • 1
    Details please. Link only answers are discouraged tend to be down voted quickly. I might add that the question is not very clear. It is only after reading the comments that it becomes obvious that what is desired is knowing which entities changed from another process while the user is looking at the form. Events are probably not going to be much help for this. – Cerad Feb 08 '19 at 13:00