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?
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'));
}
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.