My name is  
Jurgens du Toit.
Systems Developer.
Problem Solver.

About Me

Technology and Solving Problems are my passion. I'm a South African that loves my wife, life, and coding.

I'm writing a book!

The Logstash Config Guide

Buy it now on Leanpub

22 July 2013

Pre-populating an Entity in a Symfony 2 Form

By Jurgens du Toit

I’ve been working on teach-a-rific.com in my spare time, and I’m learning a lot about how Symfony 2 Forms work. One thing I need to do a lot, is to show a form with a entity field pre-populated. In this situation you also don’t want the user to be able to edit the field. This is how I did it.

First, you need to retrieve the mapped entity, in this case a Student, and set it in the entity which you’re creating a form for. In this case a ContactDetail. This all happens in the newAction method of the ContactDetailController. Notice how I save the student ID in a session variable. More on this later.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
//ContactDetailController::newAction
$detail = new ContactDetail();

if ($studentId = $request->query->get('student_id')) {
    $student = $this
        ->getDoctrine()
        ->getManager()
        ->getRepository('NotesNoteBundle:Student')
        ->find($studentId);
    if ($student) {
        $this->get('session')->set('contact_detail:create:student', $studentId);
        $detail->setStudent($student);
    }
}

$form = $this->createForm(new ContactDetailType(), $detail);

On to the form. Quite simply, if the entity already has a Student, don’t add the field for the student.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ContactDetailType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if ($builder->getData()->getStudent() === null) {
            $builder->add('student');
        }
        $builder
            ->add('type', 'choice', array('choices' => array('Email' => 'Email', 'Cellphone' => 'Cellphone')))
            ->add('content')
        ;
    }
}

On to the actual form. If the student field is defined in the form, display the form widget. Otherwise display the student in an uneditable text input. Displaying the student can be skipped if it’s not necessary.

1
2
3
4
5
6
7
8
9
10
{% if form.student is defined %}
    {{ form_row(form.student, { form_type: 'horizontal' }) }}
{% elseif form.vars.data.student.id is defined %}
    <div class="control-group">
        <label class="control-label">Student</label>
        <div class="controls">
            <span class="input uneditable-input">{{ form.vars.data.student }}</span>
        </div>
    </div>
{% endif %}

And on to the updateAction. Just get the Student whose ID we stored in the session, and set it on the ContactDetail before populating the form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
//ContactDetailController::createAction
$entity  = new ContactDetail();

if ($studentId = $this->get('session')->get('contact_detail:create:student')) {
    $student = $this
        ->getDoctrine()
        ->getManager()
        ->getRepository('NotesNoteBundle:Student')
        ->find($studentId);
    if ($student) {
        $entity->setStudent($student);
    }
}

Simple enough. Any suggestions on how to improve it, or comments on how to do it differently?

blog comments powered by Disqus