Skip to content

Instantly share code, notes, and snippets.

@webmozart
Created March 23, 2011 15:32
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save webmozart/883293 to your computer and use it in GitHub Desktop.
Save webmozart/883293 to your computer and use it in GitHub Desktop.
<?php
protected function _editAction(Post $post)
{
$em = $this->get('doctrine.orm.default_entity_manager');
$factory = $this->get('form.factory');
$form = $factory->create(new PostFormType());
$form->setData($post);
if ($this->get('request')->getMethod() === 'POST') {
$form->bindRequest($this->get('request'));
if ($form->isValid()) {
$em->persist($post);
$em->flush();
return new RedirectResponse($this->generateUrl('hello_index'));
}
}
return $this->render('MyHelloBundle:Hello:edit.html.twig', array(
'form' => $form->createView(),
));
}
<?php
namespace My\HelloBundle\Form;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\Type\AbstractType;
use My\HelloBundle\Entity\Comment;
class PostFormType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('title')
->add('file')
->add('content')
->add('abstract')
->add('enabled')
->add('publicationDateStart', 'date')
->add('commentsDefaultStatus', 'choice', array(
'choices' => Comment::getStatusCodes(),
))
// the second parameter, $type, is null because we use auto-creation
->add('tags', null, array(
'expanded' => true,
'multiple' => true,
))
->build('author', 'form', array('data_class' => 'My\HelloBundle\Entity\Author'))
->add('firstName')
->add('lastName')
->end();
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'My\HelloBundle\Entity\Post',
);
}
public function getName()
{
return 'postform';
}
}
{% form_theme form _self %}
{{ form_enctype(form) }}
{{ form_widget(form) }}
{{ form_widget(form.firstName) }}
{% for child in form %}
{{ form_widget(child) }}
{% endfor %}
{{ form_widget(form.firstName, { 'attr': { 'class': 'foobar' } }) }}
{{ form_label(form.firstName, 'My label') }}
@docteurklein
Copy link

How do you handle something kind like EntityChoiceList ? do I have to create my "choices" option array manually ?

@webmozart
Copy link
Author

@docteurklein Care to elaborate your question?

@docteurklein
Copy link

Sorry if misunderstood :)

I want my form to display a select box corresponding to all the elements of a mongo database collection.
For that, I get an array of Documents and pass it to my choice type via the choices options.

the problem is that the dataTransformer attached to the choice type is a ScalarToChoiceTransformer and it can't handle Object transformation.

FormType:

        $builder->add('frontend_template', 'choice', array(
            'choices' => $this->getTemplateChoices() // this is an array containing Objects
        ))

@docteurklein
Copy link

I finally implemented my own DataTransformer and replaced the Scalar one.

Here is how I did:

$builder->get('frontend_template')->resetClientTransformers();
$builder->get('frontend_template')->appendClientTransformer(new DocumentToChoiceTransformer($this->dm, 'Test\Document\Template'));

Transformer:

<?php

namespace Test\BlockBundle\Form;

use Doctrine\ODM\MongoDB\DocumentManager;

use Symfony\Component\Form\DataTransformerInterface;
use Test\Form\ToIdTransformable;

class DocumentToChoiceTransformer implements DataTransformerInterface
{
    private $dm;
    private $className;

    public function __construct(DocumentManager $dm, $className) 
    {
        $this->dm = $dm;
        $this->className = $className;
    }

    public function transform($value)
    {
        if(null === $value) {

            return '';
        }

        if(is_scalar($value)) {
            return $this->dm->getRepository($this->className)->find($value);
        }

        if( ! $value instanceof ToIdTransformable) {
            throw new \InvalidArgumentException(sprintf('Object must implement "ToIdTransformable" interface'));
        }

        return $value->getId();
    }

    public function reverseTransform($value)
    {
        if(is_scalar($value)) {
            return $this->dm->getRepository($this->className)->find($value);
        }
    }
}

@hectorh30
Copy link

very helpful! thanks

@docteurklein
Copy link

I forgot to say that your domain objects must implement the ToIdTransformable interface:

interface ToIdTransformable
{
    function getId();
}

@docteurklein
Copy link

But I really would like to have the thoughts of @bschussek on this :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment