Symfony2 (2.7) Form Entity Data Transformer - forms

I'm trying to customize a selection list's text while using the entity's ID. This is because I want the list options to be specific to the authenticated user. The database text values are Full Name, By City and State, and Anonymous, but I want it to actually display the user's full name (John Smith), User in Denver, CO, and Anonymous. I'm attempting to use a view data transformer to achieve this, but with no luck. I'd rather not use Javascript to achieve this if possible.
Here's my main form type:
<?php
namespace Members\MessagesBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\SecurityContext;
class MessageType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('viewability', 'viewability_entity', array(
'class' => 'MessagesBundle:Viewability',
'property' => 'name',
'required' => true,
))
->add('body', new MessageBodyType())
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Members\MessagesBundle\Entity\Message',
));
}
/**
* #return string
*/
public function getName()
{
return 'members_messages_message';
}
}
Here's my custom form type for Viewability (the entity which I would like to transform):
<?php
namespace Members\MessagesBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\SecurityContext;
use Members\MessagesBundle\Form\DataTransformer\MessageNameTransformer;
class ViewabilityType extends AbstractType
{
private $context;
/**
* #param SecurityContext $context
*/
public function __construct(SecurityContext $context)
{
$this->context = $context;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new MessageNameTransformer($this->context);
$builder->addViewTransformer($transformer);
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'invalid_message' => 'The selected issue does not exist',
));
}
/**
* #return string
*/
public function getParent()
{
return 'entity';
}
/**
* #return string
*/
public function getName()
{
return 'viewability_entity';
}
}
Here's my service which defines the Viewability Type:
members.messages.form.type.viewability_entity:
class: Members\MessagesBundle\Form\ViewabilityType
tags:
- { name: form.type, alias: viewability_entity }
arguments: [#security.context]
Here's my Viewability Entity:
<?php
namespace Members\MessagesBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity()
*/
class Viewability
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
public function __construct()
{
}
/**
* #return mixed
*/
public function getName()
{
return $this->name;
}
/**
* #param mixed $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #param mixed $id
*/
public function setId($id)
{
$this->id = $id;
}
}
Finally, here's my data transformer:
<?php
namespace Members\MessagesBundle\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
use Members\MessagesBundle\Entity\Viewability;
use Symfony\Component\Security\Core\SecurityContext;
class MessageNameTransformer implements DataTransformerInterface
{
private $user;
/**
* #param SecurityContext $context
*/
public function __construct(SecurityContext $context)
{
$this->user = $context->getToken()->getUser();
}
/**
* #param Viewability|null $viewability
* #return string
*/
public function transform($viewability)
{
if (null === $viewability) {
return '';
}
if($viewability === 'Full Name')
return sprintf('%s %s', $this->user->getInfo()->getFirstName(), $this->user->getInfo()->getLastName());
if($viewability === 2)
return sprintf('Lawyer in %s, %s', $this->user->getInfo()->getAddress()->getCity(), $this->user->getInfo()->getAddress()->getState());
if($viewability === 3)
return 'Anonymous';
}
/**
* #param Viewability $viewability
* #return Viewability
*/
public function reverseTransform($viewability)
{
return $viewability;
}
}
The data passed into transform() always seems to be null or "" (empty string).
Thanks for any help.

So I ended up taking a different approach to solving this. Originally I was trying to transform data coming from an entity. Fortunately this entity didn't really need to be a database entity after all and a simple choice type sufficed. This doesn't solve the specific issue of transforming an entity list, but it allows me to customize the drop down list values.
The viewability entity was removed and the relationship in the Message entity was changed to an integer field.
My main type is now as follows:
class MessageType extends AbstractType
{
private $user;
public function __construct($user)
{
$this->user = $user;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('body', new MessageBodyType())
->add('viewability', 'choice', array(
'choices' => array(
1 => $user->getFirstName(),
2 => $user->getAddress()->getCity(),
3 => 'Anonymous',
),
'multiple' => false,
'label' => 'Send Message As',
'data' => 0,
))
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Members\MessagesBundle\Entity\Message',
));
}
/**
* #return string
*/
public function getName()
{
return 'members_messages_message';
}
}

Related

Symfony Entity Field Type where clause in Query Builder not working on One-To-Many self referencing association

I have an Entity called "InterestGroup" that has a self referencing association (adjacency list) in the form of properties "children" (one to many) and "parent" (many to one).
In setting up a form type for InterestGroup, I'm attempting to provide a select list for the property parent, that has choices of all 'top level' interest groups (those whose 'parent' property is null). When I add the the where clause and null parameter to the query_builder for the EntityType field, it always returns nothing, even when I have several top level (parent is null) interest groups persisted. If I remove the where clause it will return all InterestGroups in the table. I'm having a difficult time understanding why the where clause is not working.
This is the field in question:
->add('parent',EntityType::class,
array(
'placeholder' => 'Top Level (No Parent)',
'required' => false,
'class' => 'Common\ContentBundle\Entity\InterestGroup',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('ig')
->where('ig.parent = :n')
->setParameter('n',null)
->orderBy('ig.title', 'ASC');
},
'choice_label' => 'title'
)
)
The above will return an empty select menu. By removing the where clause and the setparameter, I get all the InterestGroup Entities including all those that have null parents.
Following is the Entity Class for InterestGroup
<?php
namespace Common\ContentBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* InterestGroup
*
* #ORM\Table(name="interest_group")
* #ORM\Entity(repositoryClass="Common\ContentBundle\Repository\InterestGroupRepository")
*/
class InterestGroup
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255, unique=true)
* #Assert\NotBlank(message="This is a required field.")
*/
private $title;
/**
* #ORM\OneToMany(targetEntity="InterestGroup", mappedBy="parent")
*/
private $children;
/**
* #ORM\ManyToOne(targetEntity="InterestGroup", inversedBy="children")
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id")
*/
private $parent;
/**
* #Gedmo\Slug(fields={"title"})
* #ORM\Column(length=128, unique=true)
*/
private $slug;
// ...
/**
* #ORM\ManyToMany(targetEntity="Product", mappedBy="interestGroups")
*/
private $products;
/**
* InterestGroup constructor.
*/
public function __construct()
{
$this->children = new ArrayCollection();
$this->products = new ArrayCollection();
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* #param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* #return mixed
*/
public function getSlug()
{
return $this->slug;
}
/**
* #return mixed
*/
public function getChildren()
{
return $this->children;
}
/**
* #param mixed $children
*/
public function setChildren($children)
{
$this->children = $children;
}
/**
* #return mixed
*/
public function getParent()
{
return $this->parent;
}
/**
* #param mixed $parent
*/
public function setParent($parent)
{
$this->parent = $parent;
}
/**
* #return mixed
*/
public function getProducts()
{
return $this->products;
}
}
And the Form Type Class:
<?php
namespace Common\ContentBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
class InterestGroupType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title',TextType::class)
->add('parent',EntityType::class,
array(
'placeholder' => 'Top Level (No Parent)',
'required' => false,
'class' => 'Common\ContentBundle\Entity\InterestGroup',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('ig')
->where('ig.parent = :n')
->setParameter('n',null)
->orderBy('ig.title', 'ASC');
},
'choice_label' => 'title'
)
)
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Common\ContentBundle\Entity\InterestGroup'
));
}
}
Thanks in advance!
Check you code here:
return $er->createQueryBuilder('ig')
->where('ig.parent = :n') // <---
->setParameter('n',null) // <---
->orderBy('ig.title', 'ASC');
It is the same to:
... WHERE ig.parent = NULL ...
So, this query always returns null dataset.
Right code:
return $er->createQueryBuilder('ig')
->where('ig.parent IS NULL')
->orderBy('ig.title', 'ASC');
Use IS NULL for checking null values.
This problem is related to what is "=null" and " IS NULL"

Same Table, Two entities (or class) in symfony

I'd like to build two class that refer to the same table.
For example:
Table Invoice:
idInvoice, IdClient, idProduct.
I've got one entity that shows general information (idClient and idInvoice) and than I've got an entity that allows me to show a dynamically generated form (id Product).
For every invoice I need one or more product so I should be able to insert different row for different product.
How can I link this different entities on the same table?
When I submit the form I need to extract all data from Product information and all data from Client and then I need to insert on MySQL.
I have got ORDER TABLE and PRODUCT TABLE. They are in a one to many relationship (one order, more product.) I created two entities: Order and Product and these are the classes:
ORDER CLASS
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="ordini")
*/
class Ordine
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $idOrdine;
/**
*
* #ORM\OnetoMany(targetEntity="Prodotto", cascade={"persist"},
mappedBy="prodotto")
*
*/
protected $prodotti;
/**
* Get idOrdine
*
* #return integer
*/
public function getIdOrdine()
{
return $this->idOrdine;
}
public function __costruct()
{
$this->prodotti= new ArrayCollection();
}
public function setProdotti(ArrayCollection $prodotti)
{
$this->prodotti = $prodotti;
//return $this;
}
public function addProdotti(Prodotto $prod) {
$this->prodotti[] = $prod;
return $this;
}
public function addProdotto(Prodotto $prodotto) {
$this->prodotti[] = $prodotto;
$prodotto->setOrdine($this);
return $this;
}
public function getProdotti() {
return $this->prodotti;
}
}
PRODUCT CLASS
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="prodotto")
*/
class Prodotto
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $idProdotto;
/**
* #ORM\Column(type="string", length=100, nullable=TRUE)
*
*/
protected $modello;
/**
* #ORM\ManyToOne(targetEntity="Ordine", inversedBy="prodotti")
* #var AppBundle\Entity\Ordine
*/
protected $ordini;
/**
* Get idProdotto
*
* #return integer
*/
public function getIdProdotto()
{
return $this->idProdotto;
}
/**
* Set modello
*
* #param string $modello
* #return Prodotto
*/
public function setModello($modello)
{
$this->modello = $modello;
return $this;
}
/**
* Get modello
*
* #return string
*/
public function getModello()
{
return $this->modello;
}
}
Then I created a Form that allows me to create an order (invoice) and I can dynamically generate Product Field.
I should be on the right way but now it gives me an error:
Expected argument of type "Doctrine\Common\Collections\ArrayCollection",
"array" given
My OrderForm is:
namespace AppBundle\Form\Documentofiscale;
use Symfony\Component\Form\TextField;
use Symfony\Component\Form\Checkbox;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use AppBundle\Entity\Prodotto;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class FormDocumentoFiscale extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// $builder->add('idCliente');
//$builder->add('save', 'submit', array('label' => 'INSERISCI
DOCUMENTO'));
$builder->add('prodotti', 'collection', array(
'type' => new FormAggiuntaProdotti(),
'allow_add' => true,
'by_reference' => false,
)
);
$builder->add('save', 'submit', array('label' => 'INSERISCI
DOCUMENTO'));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Ordine',
));
}
public function getName()
{
return 'documento';
}
}
And my dynamically generated Form is:
namespace AppBundle\Form\Documentofiscale;
use Symfony\Component\Form\TextField;
use Symfony\Component\Form\Checkbox;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use AppBundle\Entity\Prodotto;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class FormAggiuntaProdotti extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('modello');
//// $builder->add('idCliente');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Prodotto',
));
}
public function getName()
{
return 'prodotto';
}
}

Symfony: unable to handle request in form

I have 3 form types (SearchForm - SearchField - SearchFieldType), each one including next like this:
SearchFormType:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class SearchFormType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('fields', 'collection', array('type' => new SearchFieldType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false))
->add('submit', 'submit', array('label' => "Buscar"))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\SearchForm',
'allow_extra_fields' => true,
'csrf_protection' => false,
'validation_groups' => false,
));
}
/**
* #return string
*/
public function getName()
{
return 'appbundle_searchform';
}
}
SearchFieldType:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class SearchFieldType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'hidden')
->add('slug', 'hidden')
->add('value')
->add('choices')
->add('type', new SearchFieldTypeType())
->add('actionFilter')
->add('actionHighlight')
->add('actionShow')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\SearchField'
));
}
/**
* #return string
*/
public function getName()
{
return 'appbundle_searchfield';
}
}
SearchFieldTypeType:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use AppBundle\Entity\SearchOperator;
class SearchFieldTypeType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$entity = $builder->getData();
$builder
->add('name', 'hidden')
->add('operators', 'entity', array('class' => 'AppBundle:SearchOperator',
'multiple' => false,
'expanded' => false))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\SearchFieldType'
));
}
/**
* #return string
*/
public function getName()
{
return 'appbundle_searchfieldtype';
}
}
The form renders properly, but when I submit and try to do $form->handleRequest($request) I get an exception:
Neither the property "operators" nor one of the methods "addOperator()"/"removeOperator()", "setOperators()", "operators()", "__set()" or "__call()" exist and have public access in class "AppBundle\Entity\SearchFieldType"
That's not true actually, as those methods exist and work correctly:
AppBundle\Entity\SearchFieldType:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\SearchOperator;
/**
* SearchField
*
* #ORM\Table()
* #ORM\Entity
*/
class SearchFieldType
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=100, nullable=true)
*/
private $name;
/**
* #ORM\ManyToMany(targetEntity="SearchOperator", cascade={"persist", "remove"})
* #ORM\JoinTable(
* joinColumns={#ORM\JoinColumn(name="type_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="operator_id", referencedColumnName="id")}
* )
**/
private $operators;
/**
* Constructor
*/
public function __construct()
{
$this->operators = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return SearchFieldType
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Add operator
*
* #param SearchOperator $operator
*
* #return SearchFieldType
*/
public function addOperator(SearchOperator $operator)
{
$this->operators[] = $operator;
return $this;
}
/**
* Remove operator
*
* #param SearchOperator $operator
*/
public function removeOperator(SearchOperator $operator)
{
$this->operators->removeElement($operator);
}
/**
* Get operator
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getOperators()
{
return $this->operators;
}
public function __toString()
{
return $this->name;
}
}
Stack trace:
in vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php at line 460 +
at PropertyAccessor ->writeProperty (object(SearchFieldType), 'operators', object(SearchOperator))
in vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php at line 104 +
at PropertyAccessor ->setValue (object(SearchFieldType), object(PropertyPath), object(SearchOperator))
in vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php at line 93 +
at PropertyPathMapper ->mapFormsToData (object(RecursiveIteratorIterator), object(SearchFieldType))
in vendor/symfony/symfony/src/Symfony/Component/Form/Form.php at line 633 +
at Form ->submit (array('operators' => '156', 'name' => 'string'), true)
in vendor/symfony/symfony/src/Symfony/Component/Form/Form.php at line 577 +
at Form ->submit (array('type' => array('operators' => '156', 'name' => 'string'), 'value' => 'felipe', 'name' => 'Nombre', 'slug' => 'nombre'), true)
in vendor/symfony/symfony/src/Symfony/Component/Form/Form.php at line 577
EDIT:
Controller Code :
$searchFormEntity = new SearchForm();
$searchFormWithValues = $this->createForm(new SearchFormType(), $searchFormEntity, array(
'action' => $this->generateUrl('candidato'),
'method' => 'POST'
));
$searchFormWithValues->add('submit', 'submit', array('label' => 'Buscar'));
$searchFormWithValues->handleRequest($request);
Well you have a ManyToMany relation, so it would make sense to have the operators field be a collection. However you defined it as an entity, so now the form expects to have the setOperators and getOperators methods as entity implies a ManyToOne or OneToOne relationship.
I think you need to change the statement in the class SearchFieldTypeType where adding the operators attribute to be the same as what you did before for fields in SearchFormType if you want to keep the ManyToMany relationship.

Error using A2lix as an embedded form

I'm using A2lix Translation Form Bundle and Doctrine Behaviors Translatable in a project where I have two entities: company and files. Company has some translatable fields so I have a CompanyTranslations Entity for that. One company can have one file so Company and file are mapped with an OneToOne unidirectional reference. The company file is translatable so the property is in the CompanyTranslation file.
CompanyTranslation:
class CompanyTranslation
{
use ORMBehaviors\Translatable\Translation;
/**
* #ORM\OneToOne(targetEntity="File", cascade={"persist"})
* #ORM\JoinColumn(name="translatable_file_id", referencedColumnName="id")
* #Assert\Valid()
* #Assert\Type(type="MyApp\CoreBundle\Entity\File")
**/
private $translatableFile;
/**
* Set translatableFile
*
* #param $translatableFile
*/
public function setTranslatableFile(File $translatableFile = null)
{
$this->translatableFile = $translatableFile;
}
/**
* Get translatableFile
*
* #return $translatableFile
*/
public function getTranslatableFile()
{
return $this->translatableFile;
}
}
File:
class File
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
public $filePath;
/**
* #Assert\File()
*/
private $file;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set filePath
*
* #param string $filePath
*/
public function setFilePath($filePath)
{
$this->filePath = $filePath;
}
/**
* Get filePath
*
* #return string
*/
public function getFilePath()
{
return $this->filePath;
}
/**
* Set file
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
}
/**
* Get file
*
* #return UploadedFile
*/
public function getFile()
{
return $this->file;
}
}
File Form Type:
class FileType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('file', 'file', array(
'label' => false
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MyApp\CoreBundle\Entity\File'
));
}
public function getName()
{
return 'file_form';
}
}
Company Form Type:
class CompanyType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('translations', 'a2lix_translationsForms', array(
'locales' => $this->languages,
'form_type' => new FileType(),
'form_options' => array(
'data_class' => 'MyApp\CoreBundle\Entity\File',
'required' => false,
'validation_groups' => array('file_upload')
)
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
parent::setDefaultOptions($resolver);
$resolver->setDefaults(array(
'data_class' => 'MyApp\CoreBundle\Entity\Company'
));
}
}
The error is this one:
The form's view data is expected to be an instance of class MyApp\CoreBundle\Entity\File, but is an instance of class MyApp\CoreBundle\Entity\CompanyTranslation. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms an instance of class MyApp\CoreBundle\Entity\CompanyTranslation to an instance of MyApp\CoreBundle\Entity\File.
I already set the data_class of the File Type Form and the data_class of the field to null but also to MyApp\CoreBundle\Entity\File. Both send me errors. I don't know what's happening.
Could anyone help?
Thanks!

Data Transformer choice type linked to an entity

I hope you'll understand well...
I have an Entity : 'Models' which contains an attribut 'spokenlangs' format like that : ,es_ES,fr_FR,
I have an Entity : 'Langs' which contains an attribut 'title' (Ex : Español) and an attribute code (Ex : es_ES).
The BDD schema is imposed and non alterable.. (For my bad !). No link exists between this two entities (tables..).
I would like to create an edit form for Models where the field spokenlangs :
is a multiple choice check box
is displayed by title ( attribut title in Langs entity)
is stored in Models like ,es_ES,us_US (etc if user check several languages)
My file ModelsType :
class ModelsType extends \MyProject\AdminBundle\Form\Type\ModerationAbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
// $spokenlangTransformer = new SpokenLangsTransformer($this->entityManager);
$builder
->add( $this->getLangsField( $builder, 'spokenlangs', array('multiple' => true, 'expanded' => true) ))
->add( 'user', new UserType($this->entityManager) )
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MyProject\EntityBundle\Entity\Models'
));
}
/**
* #return string
*/
public function getName()
{
return 'myproject_entitybundle_models';
}
}
My ModerationAbstractType file (where getLangsField() is defined)
namespace MyProject\AdminBundle\Form\Type;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use MyProject\AdminBundle\Form\Transformer\CountryTransformer;
use MyProject\AdminBundle\Form\Transformer\SpokenLangsTransformer;
/**
* Centralyze user form type
*/
abstract class ModerationAbstractType extends AbstractType
{
/** #var EntityManager */
protected $entityManager;
/**
*
* #param EntityManager $entityManager
*/
public function __construct( EntityManager $entityManager )
{
$this->entityManager = $entityManager;
}
/**
* Return a lang field linked to the langs list by code
* #param type $name
* #param array $options
* #return type
*/
public function getLangsField($builder, $name, $options){
$transformer = new SpokenLangsTransformer($this->entityManager);
return $builder->create($name, 'choice', $options)
->addModelTransformer($transformer);
}
}
And my SpokenLangsTransformer file :
namespace MyProject\AdminBundle\Form\Transformer;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use MyProject\EntityBundle\Entity\Wmlangs;
/**
* Description of SpokenLangsTransformer
*
*
*/
class SpokenLangsTransformer implements DataTransformerInterface {
/**
* #var ObjectManager
*/
private $om;
/**
* #param ObjectManager $om
*/
public function __construct(ObjectManager $om) {
$this->om = $om;
}
/**
* Transforms an object (wmlangs) to a string (code).
*
* #param Wmlangs|null $spokenlangs
* #return string
*/
public function transform($spokenlangs) {
if (null === $spokenlangs) {
return "";
}
$codeArray = array_filter(explode(",", $spokenlangs));
foreach ($codeArray as $code) {
$spokenlangsArray[] = $this->om
->getRepository('MyProject\EntityBundle\Entity\Wmlangs')
->findOneBy(array('code' => $code));
}
foreach($spokenlangsArray as $namelang) {
$namesLangs[] = $namelang->getTitle();
}
return $namesLangs;
}
/**
* Transforms a string (number) to an object (issue).
*
* #param string $number
* #return Wmlangs|null
* #throws TransformationFailedException if object (wmlangs) is not found.
*/
public function reverseTransform($codes) {
if (!$codes) {
return null;
}
$codeArray = array_filter(explode(",", $codes));
foreach ($codeArray as $code) {
$spokenlangs[] = $this->om
->getRepository('MyProject\EntityBundle\Entity\Wmlangs')
->findOneBy(array('code' => $code));
}
if (null === $spokenlangs) {
throw new TransformationFailedException(sprintf(
'Le problème avec le code "%s" ne peut pas être trouvé!', $code
));
}
return $spokenlangs;
}
}
With this actual code the field does not display anything..
Please, how can I do to add what I expect ?
NB : note that when I tried to access the form it passes in transform function (in my datatransformer.. I think it's not right )
Try 'entity' form filed at getLangsField function