Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make a form with a bunch of unrelated entities in Symfony2?

Tags:

forms

php

symfony

I'm working on a log parser that uses a database table to "translate" log events into human-readable equivalents for reporting.

For example, a log entry like "start_application_minecraft" would get converted to "Started Minecraft".

I'm trying to make a web interface for adding/updating the display text, but I can't figure out how to get them into a Symfony Form object.

I have a LogEvent entity (with properties for ID, Text, and DisplayText), and I've created a Form Type that corresponds to these properties.

It works fine for modifying one event at a time, but I'd like to have them all on one page with a single Submit button to update everything. The problem is that all the documentation I can find on embedding Forms deals with entities that are related (e.g. a Category containing multiple Products), but in my case all of the entities I need to work with are completely unrelated. What's the best way to go about setting this up?

like image 603
DarkMorford Avatar asked Oct 20 '22 20:10

DarkMorford


2 Answers

Use a Symfony 'Collection' form field type and use Doctrine to find the LogEvent entities you want and pass that to the Collection.

Example: http://symfony.com/doc/current/cookbook/form/form_collections.html

Reference: http://symfony.com/doc/current/reference/forms/types/collection.html

So, first you would make your LogEvent form type:

class LogEventType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('text');
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'My\Bundle\Entity\LogEvent',
        ));
    }

    public function getName()
    {
        return 'log_event';
    }
}

Then make your form type that holds the Collection of LogEvent entities:

class MultiLogEventType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add(
            'logEvents', 'collection', array('type' => new LogEventType())
        );
    }

    public function getName()
    {
        return 'multi_log_event';
    }
}

Then in your Controller, create the form and pass your log events to it:

public function indexAction()
{
    // replace findAll() with a more restrictive query if you need to
    $logEvents = $this->getDoctrine()->getManager()
        ->getRepository('MyBundle:LogEvent')->findAll();

    $form = $this->createForm(
        new MultiLogEventType(),
        array('logEvents' => $logEvents)
    );

    return array('form' => $form->createView());
}

Then in your edit action you can loop through the log events and do whatever you need to:

public function editAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();

    $editForm = $this->createForm(new MultiLogEventType());
    $editForm->handleRequest($request);

    if ($editForm->isValid())
    {
        foreach ($logEvents as $logEvent) {
            // perform any logic you need to here
            // (ex: removing the log event; $em->remove($logEvent);)
        }
        $em->flush();
    }

    return $this->redirect($this->generateUrl('log_event_edit'));
}
like image 127
Jason Roman Avatar answered Oct 22 '22 12:10

Jason Roman


You can create a Form Type, which adds all the entities as children. IF you make your "data" an array, you can have an arbitrary number of form items.

like image 42
Daniel Avatar answered Oct 22 '22 13:10

Daniel