Skip to content

Instantly share code, notes, and snippets.

@hidenorigoto
Last active August 29, 2015 13:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hidenorigoto/8884909 to your computer and use it in GitHub Desktop.
Save hidenorigoto/8884909 to your computer and use it in GitHub Desktop.
<?php
namespace Acme\DemoBundle\Controller;
use Acme\DemoBundle\Form\Entity\Item;
use Acme\DemoBundle\Form\Entity\Tag;
use Acme\DemoBundle\Form\Type\ItemWithTagsType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Acme\DemoBundle\Form\ContactType;
// these import the "@Route" and "@Template" annotations
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class DemoController extends Controller
{
/**
* @Route("/contact", name="_demo_contact")
* @Template()
*/
public function contactAction(Request $request)
{
$data = new Item();
$tag1 = new Tag();
$tag1->name = 'PHP';
$tag2 = new Tag();
$tag2->name = 'Ruby';
$data->tags = [$tag1, $tag2];
$form = $this->createForm(new ItemWithTagsType(), $data);
$form->handleRequest($request);
if ($form->isValid()) {
var_dump($form->getData());
}
return array('form' => $form->createView());
}
}
<?php
namespace Acme\DemoBundle\Form\Entity;
use Symfony\Component\Validator\Constraints As Assert;
class Item
{
public $id;
/**
* @Assert\NotBlank
*/
public $name;
/**
* @assert\Valid
*/
public $tags = [];
}
<?php
namespace Acme\DemoBundle\Form\Entity;
use Symfony\Component\Validator\Constraints As Assert;
class Tag
{
public $id;
/**
* @Assert\Length(max=10)
*/
public $name;
public function __construct($id = null, $name = null)
{
$this->id = $id;
$this->name = $name;
}
}
<?php
namespace Acme\DemoBundle\Form\Transformer;
use Acme\DemoBundle\Form\Entity\Tag;
use Acme\DemoBundle\Repository\TagRepository;
use Symfony\Component\Form\DataTransformerInterface;
class TagsToTextTransformer implements DataTransformerInterface
{
private $tagRepository;
public function __construct(TagRepository $tagRepository)
{
$this->tagRepository = $tagRepository;
}
public function transform($value)
{
return array_reduce($value, function ($current, $element) {
if ($current != '') {
$current .= ' ';
}
return $current . $element->name;
}, '');
}
public function reverseTransform($value)
{
$newTags = explode(' ', $value);
$allTags = $this->tagRepository->findAll();
$existingTags = array_filter($allTags, function ($element) use (&$newTags) {
if (($foundIndex = array_search($element->name, $newTags)) !== false) {
array_splice($newTags, $foundIndex, 1);
}
return $foundIndex !== false;
});
$tags = array_reduce($newTags, function ($current, $element) {
$current[] = new Tag(null, $element);
return $current;
}, $existingTags);
return $tags;
}
}
<?php
namespace Acme\DemoBundle\Form\Type;
use Acme\DemoBundle\Form\Entity\Item;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ItemWithTagsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', 'text')
->add('tags', 'tags'])
->add('submit', 'submit')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
[
'data_class' => Item::class,
]
);
}
public function getName()
{
return 'itemwithtags';
}
}
<?php
namespace Acme\DemoBundle\Form\Type;
use Acme\DemoBundle\Form\Transformer\TagsToTextTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class TagsType extends AbstractType
{
private $transformer;
public function setTagsToTextTransformer(TagsToTextTransformer $transformer)
{
$this->transformer = $transformer;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addModelTransformer($this->transformer);
}
public function getParent()
{
return 'text';
}
public function getName()
{
return 'tags';
}
}
<?php
namespace Acme\DemoBundle\Repository;
use Acme\DemoBundle\Form\Entity\Tag;
class TagRepository
{
public function findAll()
{
return [
new Tag(1, 'PHP'),
new Tag(2, 'Ruby'),
new Tag(3, 'Python'),
new Tag(4, 'Java')
];
}
}
services:
acme.demo.formtype.tags:
class: Acme\DemoBundle\Form\Type\TagsType
tags:
- { name: form.type, alias: tags }
calls:
- [setTagsToTextTransformer, [@acme.demo.formtransformer.tagstotext]]
acme.demo.repository.tag_repository:
class: Acme\DemoBundle\Repository\TagRepository
# for normal ORM repository see http://stackoverflow.com/questions/12223176/how-to-inject-a-repository-into-a-service-in-symfony2
acme.demo.formtransformer.tagstotext:
class: Acme\DemoBundle\Form\Transformer\TagsToTextTransformer
arguments: [@acme.demo.repository.tag_repository]
{% extends "AcmeDemoBundle::layout.html.twig" %}
{% block title "Symfony - Contact form" %}
{% block content %}
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_row(form.name) }}
{{ form_row(form.tags) }}
{{ form_rest(form) }}
{% endblock %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment