Doctrine Embeddables not working with Symfony forms - forms

Has anyone encountered this problem when using doctrine embeddables and symfony forms?
if you don't know Doctrine Embeddables are, you can read about it here
http://doctrine-orm.readthedocs.org/en/latest/tutorials/embeddables.html
When using value object (CategoryType in my case) with symfony form on form submission (during persisting to DB) I get the following warning
Warning: ReflectionProperty::getValue() expects parameter 1 to be object, string given
This happens because symfony form returns string instead of embeddable object.
The only workaround I have right now is to use mapped => false on type field and create valid embeddable object inside controller action just before persist. But that's far from "nice" solution and I want to avoid that.
My Entity, Value Object and form (simplified for the sake of question)
Foo\BarBundle\Entity\CategoryType
<?php
namespace Foo\BarBundle\Entity;
class CategoryType
{
/**
* #var string
*/
protected $value;
public function __toString()
{
return (string) $this->getValue();
}
/**
* #return string
*/
public function getValue()
{
return $this->value;
}
/**
* #param string $value
*
* #return $this
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
}
Foo\BarBundle\Resources\config\doctrine\CategoryType.orm.yml
CategoryType.orm.yml
Foo\BarBundle\Entity\CategoryType:
type: embeddable
fields:
value:
type: string
Foo\BarBundle\Entity\Category
<?php
namespace Foo\BarBundle\Entity;
class Category
{
/**
* #var integer
*/
protected $id;
/**
* #var string
*/
protected $name;
/**
* #var CategoryType
*/
protected $type;
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #return \Foo\BarBundle\Entity\CategoryType
*/
public function getType()
{
return $this->type;
}
/**
* #param \Foo\BarBundle\Entity\CategoryType $type
*
* #return $this
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* #return string
*/
public function __toString()
{
return (string) $this->getName();
}
/**
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #param string $name
*
* #return $this
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
}
Foo\BarBundle\Resources\config\doctrine\Category.orm.yml
Foo\BarBundle\Entity\Category:
type: entity
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
name:
type: string
embedded:
type:
class: CategoryType
Foo\BarBundle\Form\CategoryType
<?php
namespace Foo\BarBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CategoryType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('type')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'Foo\BarBundle\Entity\Category'
)
);
}
/**
* #return string
*/
public function getName()
{
return 'category_form';
}
}

The doctrine embedabble behavior is just a persistence mechanism, so, it can not break the form component which is independant from it (and works with all objects graph).
The issue is your form is not well designed (it does not follow your object graph). Here, you have a category which wraps a category type. So, your form must follow the same structure at the definition level.
You must create a CategoryTypeType form (mapped to your CategoryType class) where your add a value field. Then, in your CategoryType (the form one), you must embed the CategoryTypeType for the type field.
Then, the form component will automatically creates a Category which wraps a CategoryType. Then, Doctrine will simply persists your object as embeddable and everything will work :)

Related

How to extend register form by additional fields in FOSUserBundle and Symfony3

I'm learning Symfony3 framework. At now I've build project that contain two Entities: User and Catalog. Catalog entity is for additional Company data (company name, address, and so on) - it's like a business card. Single User (but not all) is connected only with one Business Card (Catalog entity) and that's why I've decided to use two separate entities. Some users have access e.g. to backend and other ones have possibility to add and manage their one Business Card.
I want to allow user for fill in his Company details while he is registering. I'm using FOSUserBundle for User entity. At now I have registration form working but I'm stuck and need Your help with embed my CatalogType form.
CatalogType form:
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CatalogType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('address')
->add('city')
->add('province')
->add('postcode')
->add('telephone')
->add('fax')
->add('mobile')
->add('email')
->add('webpage')
->add('misc')
;
}
public function getParent()
{
return 'FOS\UserBundle\Form\Type\RegistrationFormType';
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'app_user_registration';
}
}
User entity:
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User extends BaseUser
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var
*
* #ORM\OneToMany(targetEntity="Comment", mappedBy="user")
*/
private $comments;
/**
* #var
*
* #ORM\OneToOne(targetEntity="Catalog", mappedBy="user")
*/
private $catalog;
public function __construct()
{
parent::__construct();
$this->comments = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Add comment
*
* #param \AppBundle\Entity\Comment $comment
*
* #return User
*/
public function addComment(\AppBundle\Entity\Comment $comment)
{
$this->comments[] = $comment;
return $this;
}
/**
* Remove comment
*
* #param \AppBundle\Entity\Comment $comment
*/
public function removeComment(\AppBundle\Entity\Comment $comment)
{
$this->comments->removeElement($comment);
}
/**
* Get comments
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getComments()
{
return $this->comments;
}
/**
* Set catalog
*
* #param \AppBundle\Entity\Catalog $catalog
*
* #return User
*/
public function setCatalog(\AppBundle\Entity\Catalog $catalog = null)
{
$this->catalog = $catalog;
return $this;
}
/**
* Get catalog
*
* #return \AppBundle\Entity\Catalog
*/
public function getCatalog()
{
return $this->catalog;
}
}
Catalog entity
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Catalog
*
* #ORM\Table(name="catalog")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CatalogRepository")
*/
class Catalog
{
// ... definition a lot of private variables ...
/**
* #var
*
* #ORM\OneToOne(targetEntity="User", inversedBy="catalog")
* #ORM\JoinColumn(name="user_id", nullable=true)
*/
private $user;
// ...
/**
* Set user
*
* #param \AppBundle\Entity\User $user
*
* #return Catalog
*/
public function setUser(\AppBundle\Entity\User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \AppBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
Services config file:
// app/config/services.yml
services:
app.form.registration:
class: AppBundle\Form\CatalogType
tags:
- { name: form.type, alias: app_user_registration }
When I'm trying to display register form under http://localhost:8000/register/
I'm getting an error:
Neither the property "name" nor one of the methods "getName()",
"name()", "isName()", "hasName()", "__get()" exist and have public
access in class "AppBundle\Entity\User".
I know where is the problem, but I don't know how to properly solve it so it would be great if somebody can help me where I should looking for solutions or how it should be solved.
Thanks.
CatalogType should not extend RegistrationFormType. It should be form type for AppBundle\Entity\Catalog.
You should make form type, that is based on User class (subclass of FOS\UserBundle\Model\User), and that embeds CatalogType form.
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('...', ...)
->add('tasks', CollectionType::class, array(
'entry_type' => CatalogType::class,
...
));
...
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\User',
));
}
public function getBlockPrefix()
{
return 'app_user_registration';
}
}
class CatalogType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('address')
->add('city')
->add('province')
->add('postcode')
->add('telephone')
->add('fax')
->add('mobile')
->add('email')
->add('webpage')
->add('misc')
;
}
...
}
More on embedding forms: https://symfony.com/doc/current/form/form_collections.html
More on overriding FosUserBundle forms: http://symfony.com/doc/current/bundles/FOSUserBundle/overriding_forms.html

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';
}
}

Symfony2 (2.7) Form Entity Data Transformer

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';
}
}

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

default value for entity widget in a formbuilder

I have seen a lot of topics concerning how to set default data on a form in Symfony2, but I didn't find anything about how to set default data in an entity widget with a query builder. I explain my problem :
I have two entities, communication and Status, with a relation ManyToOne.
Here is my Communication class :
class Communication{
/**
* #ORM\Id
* #ORM\Column(name="Comm_CommunicationId")
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Test\DatabaseBundle\Entity\Statut", inversedBy="communication")
* #ORM\JoinColumn(name="Comm_Status", referencedColumnName="Capt_Code")
*/
private $statut;}
And here is my Status class:
class Statut{
/**
* #ORM\Id
* #ORM\Column(name="Capt_CaptionId")
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #ORM\Column(name="Capt_Code", type="string")
*/
private $code;
/**
* #ORM\Column(name="Capt_FR", type="string")
*/
private $codefr;}
I have built a CommunicationType form to allow me to modify a communication entity:
public function buildForm(FormBuilder $builder, array $options)
{
$builder -> add('caseid','text')
-> add('statut','entity', array('class' => 'Test\DatabaseBundle\Entity\Statut',
'query_builder' => function(\Test\DatabaseBundle\Entity\StatutRepository $sr){
$res = $sr->getCodeOnly();
return $res; },
'property' => 'CodeFr',
'preferred_choices' => array(1),
));}
Here is my controller:
public function ModifierAction($commid){
$comm = $this -> getDoctrine()
-> getEntityManager()
-> getRepository('Test\DatabaseBundle\Entity\Communication')
-> find($commid);
$form = $this -> createForm(new CommunicationType($em), $comm);
....
}
I give you the setter and the getter of my entities :
communication :
/**
* Set id
*
* #param integer $Id
*/
public function setId($Id)
{
$this -> id = $Id;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
Status entity :
/**
* Set id
*
* #param integer $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
} /**
* Set code
*
* #param string $code
*/
public function setCode($code)
{
$this->code = $code;
}
/**
* Get code
*
* #return string
*/
public function getCode()
{
return $this->code;
} /**
* Add communication
*
* #param Acme\StoreBundle\Entity\Communication $communication
*/
public function addCommunication(\Test\DatabaseBundle\Entity\Communication $communication)
{
$this->communication[] = $communication;
}
/**
* Get communication
*
* #return Doctrine\Common\Collections\Collection
*/
public function getCommunication()
{
return $this->ccommunication;
} public function __construct()
{
$this->communication = new ArrayCollection();
}
you said doctrine automatically check the object. Do you that , normally, doctrine execute the query and search, in the database, the current value of the object and pass it as the default choice?
With this I can modify my entity, but I don't know how to put my current entity Status value as the default value for the widget "entity". The method "getCodeOnly" search in the database the value of the attibut code of status (Complete, Cancelled, InProgress, Deleted) and always passed Complete as the default value. For exemple, if an entity as the value Cancelled, I want to put Cancelled as the default value when I use this form to modify my entity.
I cannot use getData and preferred_choice to have access to the status value because preferred_choice needs an array as parameter and not an entity.
I also tried to build an array with the different values of status and passed it to my form but du to several problem with my database, it failed.
If anyone have any infomation to solve this problem, i would be happy to see it.