Symfony form builder Add instance of \DateTime - php

I'm trying since some of hour to add a \DateTime validation in a form builder
The Customer entity (Sample):
class Customer
{
/**
* #Assert\NotBlank
* #Assert\Type("\DateTime")
* #MongoDB\Field(type="date")
*/
private $birthDate;
/**
* #return \DateTime
*/
public function getBirthDate() : ? \DateTime
{
return $this->birthDate;
}
/**
* #param int $birthDate
*/
public function setBirthDate(int $birthDate) : self
{
$this->birthDate = (new \DateTime())->setTimeStamp($birthDate);
return $this;
}
}
The form builder is like this (Sample):
class CustomerType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('birthDate', DateTimeType::class, ['data_class' => \DateTime::class]);
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Customer::class,
'csrf_protection' => false
]);
}
}
When I want to submit the form, I received always a error:
The form's view data is expected to be an instance of class DateTime, but is a(n) array. You can avoid this error by setting the \"data_class\" option to null or by adding a view transformer that transforms a(n) array to an instance of DateTime.
The user is sending the good parameter:
"customer": {
"birthDate": 30459425029458,
}
I tryed to follow this solution without success
Symfony2.1 form date field: Argument 1 passed to ... must be an instance of DateTime
And the view transformer return a null value
$builder->get('birthDate')
->addModelTransformer(new CallbackTransformer(
function ($tagsAsArray) {
// transform the array to a string
return implode(', ', $tagsAsArray);
},
function ($tagsAsString) {
// transform the string back to an array
return explode(', ', $tagsAsString);
}
))
;
I tried to switch data-class option to null but the form send me a no valid value error.
How can I validate a instance of \DateTime in formBuilder?
Thanks in advance
EDIT:
Temporary bad solution:
if(isset($params['customer']['birthDate'])) {
$customer->setBirthDate($params['customer']['birthDate']);
} else {
$this->error = ['message' => 'birthDate missing'];
return false;
}

Related

Symfony and FOSRestBundle: form not filling entity data

I'm trying to build a very simple rest api with FOS Rest bundle.
The GET and DELETE methods were easy, but I'm struggling with post.
Here's my post method of a very simple entity (only has a "name" and "active" property):
/**
* #param Request $request
* #return array|View
*/
public function postSkillsAction(Request $request)
{
$skill = new Skill();
$form = $this->createForm(SkillType::class, $skill);
$form->submit($request->request->get($form->getName()));
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($skill);
$this->entityManager->flush();
return $this->redirectToRoute('skillset', ['id' => $skill->getId()], Response::HTTP_CREATED);
}
return [
'form' => $form
];
}
And this is my form:
final class SkillType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) : void
{
$builder
->add(
'name', TextType::class, [
'label' => 'fields.name'
])
->add('active', CheckboxType::class, [
'label' => 'fields.active',
'required' => false
]);
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Skill::class,
'csrf_protection' => false
]);
}
/**
* #return string
*/
public function getName() : string
{
return 'skill';
}
}
The problem is that it seems like the form is not filling the entity data, when I execute /api/skills sending by post name and active I get the following SQL error
An exception occurred while executing 'INSERT INTO skill (name, active, created_at, updated_at) VALUES (?, ?, ?, ?)' with params [null, 0, "2017-03-19 19:49:37", "2017-03-19 19:49:37"]
The form data arrives correctly, I've debug and if I do $request->request->get('name') I got the proper value.
I couldn't find any updated example, this one for instance is for symfony 2, although I tried to follow it as much as possible
https://github.com/gimler/symfony-rest-edition/blob/2.7/src/AppBundle/Controller/NoteController.php
UPDATE
If I do a var_dump of var_dump($request->request->all()); I get
array(
'name' => a,
'active' => 1
)
And here's the entity
final class Skill
{
use OptionalDateTimeTrait;
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $name;
/**
* #var integer
*/
private $active;
/**
* #return int
*/
public function getId(): int
{
return $this->id;
}
/**
* #param int $id
* #return Skill
*/
public function setId(int $id) : self
{
$this->id = $id;
return $this;
}
/**
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #param string $name
* #return self
*/
public function setName(string $name) : self
{
$this->name = $name;
return $this;
}
/**
* Set active
*
* #param boolean $active
*
* #return Skill
*/
public function setActive($active) : self
{
$this->active = $active;
return $this;
}
/**
* Get active
*
* #return boolean
*/
public function getActive()
{
return $this->active;
}
}
As you've told us, when you're calling $request->request->get('name') you get correct value. Please take a look at your code where you pass data to form:
$form->submit($request->request->get($form->getName()));
This line of code means that you're passing to form only those data, which comes as array named as your form (in your case - skill). In this case you should pass through POST such data:
skill[name]=John
skill[active]=1
If you want not to send data through POST using array wrapper, you have to submit to your form whole request:
$form->submit($request->request->all());
Both methods are technically correct, but second is in fact anti-pattern.

Symfony2 setNormalizer with defined options

I'm having a problem with Symfony options resolver where I need to specify a list of defined variables that should be normalized.
The problem is: I don't want to define all these variables again in
$resolver->setDefined();
because I have a list of defined fields in $builder and the same fields are defined in the entity SlotRequest.
Is there a different way of assigning all fields/variables from entity to resolver?
First approach:
$resolver->setDefined([
'date_form','etc..' ]);
But, it pointless because in the real world I have to normalize 10+ variables + 20 fields)
Second approach would be to parse all annotations from the entity 'SlotRequest', and then fill up an array with that object.
$resolver->setDefined($anArrayOfParsedFieldsFromEntity);
Is there a better way of doing this?
An example of using:
In controller:
$form = $this->createForm(new SlotRequestType(), new SlotRequest());
SlotRequestType:
class SlotRequestType extends AbstractType
{
/**
* #var CCriteria
*/
protected $resolved = null;
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('date_from',null,['property_path'=>'dateFrom']);
//more fields
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$this->resolved = new \CCriteria();
$resolver->setDefaults(array(
'data_class' => SlotRequest::class,
'allow_extra_fields' => true,
'method' => 'GET'
));
$resolver->setDefined([....]);// the list of fields
$resolver->setNormalizer('date_from', function (Options $options, $value) {
$dateFrom = new \DateTime($value);
$this->resolved->setStartDate($dateFrom->getTimestamp());
return $value;
});
//more normalizers
}
/**
* #return null
*/
public function getName()
{
return null;
}
/**
* #return CCriteria
*/
public function getResolved()
{
return $this->resolved;
}
Entity SlotRequest
<?php
namespace Test/Entity;
class SlotRequest
{
/**
* #var string
* #Assert\NotBlank(message="Parameter [date_from] is missing.")
* #Assert\Type(
* type="string",
* message="The value {{ value }} is not a valid {{ type }}."
* )
* #Assert\Date()
*/
public $dateFrom;
//more fields
}

Symfony 3: allow_delete in Forms not working

I have a problem with my form in Symfony 3. I have one-to-many-to-one join (Doctrine 2). It handles Orders (Order), Products (Product) and joining entity (OrderProduct), which holds amount of product in order.
I have a form for add and update order entries, which uses Collection of OrderProducts. It's all based on documentation (link).
In the form I have a button for add a product (from documentation, adds a <li> to DOM) and every added has a button for remove it (from documentation, removes <li> from DOM). This part is working - adding to and removing from DOM.
Adding products works (as at the new order, than when editting).
But my problem is with removing. Products which was succesfully deleted from form, are still appearing in $editForm->getData().
OrderProduct Form
namespace AppBundle\Form;
use AppBundle\Entity\ProductType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class OrderProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('amount')
->add('product')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'AppBundle\Entity\OrderProduct',
)
);
}
public function getName()
{
return 'app_bundle_order_product_type';
}
}
Order Form
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class OrderType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('customer')
->add('date', null, array('widget' => 'single_text'))
->add('payment', null, array('widget' => 'single_text'))
->add('processed', null, array('widget' => 'single_text'))
->add(
'orderProducts',
CollectionType::class,
array(
'entry_type' => OrderProductType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'prototype' => true,
'delete_empty' => true,
'entry_options' => array('data_class' => 'AppBundle\Entity\OrderProduct'),
)
);
}
public function configureOptions(OptionsResolver $resolver)
{
}
public function getName()
{
return 'app_bundle_order_type';
}
}
Current action in OrderController
(Adding product works, removing not)
public function editAction (Request $request, $orderId) {
$em = $this->getDoctrine()->getManager();
$order = $em->getRepository('AppBundle:Order')->find($orderId);
if (!$order) {
throw $this->createNotFoundException('No order found for id '.$orderId);
}
$editForm = $this->createForm(OrderType::class, $order);
$editForm->add('submit', SubmitType::class);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$order = $editForm->getData();
//print '<pre>';
//var_dump($order->getOrderProducts());
//die();
$orderProducts = $order->getOrderProducts();
$em->persist($order);
foreach ($orderProducts as $oneOrderProduct) {
$oneOrderProduct->setOrder($order);
$em->persist($oneOrderProduct);
}
//print '<pre>';
//var_dump($order->getOrderProducts());
//die();
$em->flush();
return $this->redirectToRoute('one_order', array('orderId' => $order->getId()));
}
return $this->render(
'order/new.html.twig', array(
'form' => $editForm->createView(),
));
}
I know that I must remove removed OrderProducts from Order in editAction, but now I can't, because from the form is sent all OrderProducts.
Order Entity
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\OrderProduct;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
/**
* #ORM\Entity
* #ORM\Table(name="order_")
*/
class Order
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Customer", inversedBy="orders")
* #ORM\JoinColumn(name="customer_id", referencedColumnName="id")
*/
private $customer;
/**
* #ORM\Column(type="date")
*/
private $date;
/**
* #ORM\Column(type="date")
*/
private $payment;
/**
* #ORM\Column(type="date")
*/
private $processed;
public function __toString()
{
return strval($this->getId());
}
/**
* #ORM\OneToMany(targetEntity="OrderProduct", mappedBy="order")
*/
private $orderProducts;
public function __construct()
{
$this->orderProducts = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set date
*
* #param \DateTime $date
*
* #return Order
*/
public function setDate($date)
{
$this->date = $date;
return $this;
}
/**
* Get date
*
* #return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* Set payment
*
* #param \DateTime $payment
*
* #return Order
*/
public function setPayment($payment)
{
$this->payment = $payment;
return $this;
}
/**
* Get payment
*
* #return \DateTime
*/
public function getPayment()
{
return $this->payment;
}
/**
* Set processed
*
* #param \DateTime $processed
*
* #return Order
*/
public function setProcessed($processed)
{
$this->processed = $processed;
return $this;
}
/**
* Get processed
*
* #return \DateTime
*/
public function getProcessed()
{
return $this->processed;
}
/**
* Set customer
*
* #param \AppBundle\Entity\Customer $customer
*
* #return Order
*/
public function setCustomer(\AppBundle\Entity\Customer $customer = null)
{
$this->customer = $customer;
return $this;
}
/**
* Get customer
*
* #return \AppBundle\Entity\Customer
*/
public function getCustomer()
{
return $this->customer;
}
/**
* Add orderProduct
*
* #param \AppBundle\Entity\OrderProduct $orderProduct
*
* #return Order
*/
public function addOrderProduct(\AppBundle\Entity\OrderProduct $orderProduct)
{
$this->orderProducts[] = $orderProduct;
return $this;
}
/**
* Remove orderProduct
*
* #param \AppBundle\Entity\OrderProduct $orderProduct
*/
public function removeOrderProduct(\AppBundle\Entity\OrderProduct $orderProduct)
{
$this->orderProducts->removeElement($orderProduct);
}
/**
* Get orderProducts
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getOrderProducts()
{
return $this->orderProducts;
}
}
But in POST it's OK as you can see here, here I removed 2 of 4 products. Problem appears in form handling.
If by_reference is set to false the underlying Order entity MUST have a method in your case called [removeOrderProduct]. What also might be the problem is that you are not specifying data_class option inside the configureOptions method. In your case if Order entity is in 'AppBundle\Entity\Order', then the configureOptions method should contain:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Order',
));
}
And I would suggest you do the same in OrderProductType class also.
My guess would be that since you haven't specified the 'data_class' option in your OrderType class, the by_reference option in the 'orderProducts' field might not be able to figure out where to look for the [removeOrderProduct] method. So set that option and make sure you have that method inside your Order entity class.
IF this is not the problem then you should provide more information about your order entity and where exactly are you calling the getData method.
Update:
Looking at your code I can't identify the problem, that might be causing the entities to not get removed. But I have spotted a few oddities in your code:
In the controller, when handling form submittions it is not necessary to call the getData method: after you call handleRequest the $order object gets updated and holds the new information (since objects are passed by reference, the form can't apply the changes without changing the original $order as well). So there is no need to $order = $form->getData(), since you have already defined the $order variable before and it holds the reference to the same object to which the form mapped the posted values.
If that does not help, I suggest you add die; statements all over the place, just to make sure that at each step the right methods are called. For instance add die; to the removeOrderProduct method, to check if its hit. If it was hit, the problem is not going to be evident from the data you have provided to us, so it will require further debugging.
Also it might not be a problem now, but if you want to remove the products not present in the list after submittion, you have to call $order->getOrderProducts and add each of the items to a new collection that holds the previous orderProducts (before submittion) and compare that to the values after submittion to figure out which ones need removing.
I solved it last night :)
This is working controller action:
/**
* #Route("/{orderId}/edit", name="edit_order", requirements={"orderId": "\d+"})
* #param Request $request
* #param $orderId
*
* #return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function editAction(Request $request, $orderId)
{
$em = $this->getDoctrine()->getManager();
$order = $em->getRepository('AppBundle:Order')->find($orderId);
if (!$order) {
return $this->redirectToRoute('new_order');
}
$originalOrderProducts = new ArrayCollection();
foreach ($order->getOrderProducts() as $orderProduct) {
$originalOrderProducts->add($orderProduct);
}
$editForm = $this->createForm(OrderType::class, $order);
$editForm->add('submit', SubmitType::class);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$orderProducts = $order->getOrderProducts();
foreach ($originalOrderProducts as $oneOriginalOrderProduct) {
if (false === $order->getOrderProducts()->contains($oneOriginalOrderProduct)) {
$order->removeOrderProduct($oneOriginalOrderProduct);
$em->remove($oneOriginalOrderProduct);
$em->flush();
}
}
foreach ($orderProducts as $oneOrderProduct) {
if ($oneOrderProduct->getAmount() == 0) {
$order->removeOrderProduct($oneOrderProduct);
$em->remove($oneOrderProduct);
} else {
if (!$originalOrderProducts->contains($oneOrderProduct)) {
$oneOrderProduct->setOrder($order);
}
$em->persist($oneOrderProduct);
}
$em->persist($order);
$em->flush();
}
return $this->redirectToRoute('order');
}
return $this->render('order/new.html.twig', array('form' => $editForm->createView()));
}

Symfony2: Removing entity from middle of collection

1. Overview
I want to be able to remove an entity from a collection using a symfony2 Form.
1.1 Problem
I can add new entities to the collection, and remove them, as long as the entity being added or removed is at the end of the collection. As soon as I remove one from the start or middle I get the following error:
When I try to do this I get this error:
Neither the property "id" nor one of the methods
"addId()"/"removeId()", "setId()", "id()", "__set()" or "__call()"
exist and have public access in class
"ApiBundle\Entity\Data\Column".
1.2 Code
Here is all the relevant code.
Data
/**
* Data
*
* #ORM\Table(name="data__data")
* #ORM\Entity(repositoryClass="ApiBundle\Repository\Data\DataRepository")
*/
class Data
{
/**
* #var integer
*
* #ORM\Column(name="id", type="string")
* #ORM\Id
* #ORM\GeneratedValue(strategy="UUID")
*/
protected $id;
/**
* #var ArrayCollection
* #ORM\OneToMany(targetEntity="Column", mappedBy="parent", cascade={"all"}, orphanRemoval=true)
*/
protected $columns;
/**
* Initialise the array collections
*/
public function __construct()
{
$this->columns = new ArrayCollection();
}
/**
* #param mixed $columns
*/
public function setColumns($columns)
{
$this->columns = $columns;
}
/**
* #param Column $column
*/
public function addColumn($column)
{
$column->setParent($this);
$this->columns->add($column);
}
/**
* #param Column $column
*/
public function removeColumn($column)
{
$this->columns->removeElement($column);
}
}
Column
/**
* Data
*
* #ORM\Table(name="data__column")
* #ORM\Entity
*/
class Column
{
/**
* #var integer
*
* #ORM\Column(name="id", type="string")
* #ORM\Id
* #ORM\GeneratedValue(strategy="UUID")
*/
protected $id;
/**
* #var Data
* #ORM\ManyToOne(targetEntity="Data", inversedBy="columns")
*/
protected $parent;
/**
* #return Data
*/
public function getParent()
{
return $this->parent;
}
/**
* #param Data $parent
*/
public function setParent($parent)
{
$this->parent = $parent;
}
}
DataFormType
class DataFormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id')
->add('columns', 'collection', array(
'type' => new ColumnFormType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'ApiBundle\Entity\Data\Data',
'csrf_protection' => false
));
}
public function getName()
{
return 'data';
}
}
ColumnFormType
class ColumnFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'ApiBundle\Entity\Data\Column',
'csrf_protection' => false
));
}
public function getName()
{
return 'data_column';
}
}
I have removed some code from these snippets for clarity
1.3 Conclusion
Like I say, I get no problems when adding or deleting from the end of the collection. But as soon as it is anywhere else it errors out.
Thanks for any help.
The error is caused by the lack of the collection key preserving.
CollectionType is high tought with ResizeListener. It fills the collection form with subforms:
public function preSetData(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
...
// Then add all rows again in the correct order
foreach ($data as $name => $value) {
$form->add($name, $this->type, array_replace(array(
'property_path' => '['.$name.']',
), $this->options));
}
}
So the every subform is mapped to the collection object (underlying data) and has the name that applies to collection index, e.g. '[0]', '[1]'. When you delete elements from the collection ResizeListener removes redundant subforms.
public function preSubmit(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
...
// Remove all empty rows
if ($this->allowDelete) {
foreach ($form as $name => $child) {
if (!isset($data[$name])) {
$form->remove($name);
}
}
}
}
Lets say there were data[columns][0][id]=1, data[columns][1][id]=2, data[columns][2][id]=3.
When you remove an element from the end - all is fine. There comes data[columns][0][id]=1, data[columns][1][id]=2 with corresponding content. Then the subform [2] will be deleted and then the element with index 2 will be deleted from the collection.
When you remove an element not at the end and you don't preserve keys - the error occurs. For example you send data[columns][0][id]=2, data[columns][1][id]=3. ResizeListener will delete the subform with index [2]. Underlying data will be overrided for the rest of subforms ([0], [1]) and their child (id). Most nested subforms are processed first.
[0] (Column)
[id]
1 => 2
[1] (Column)
[id]
2 => 3
Then PropertyPathMapper will detect that id subform's data is not equals to Column's id property value (this is underlying data of the [0]):
public function mapFormsToData($forms, &$data)
{
...
if (!is_object($data) || !$config->getByReference() || $form->getData() !== $this->propertyAccessor->getValue($data, $propertyPath)) {
$this->propertyAccessor->setValue($data, $propertyPath, $form->getData());
}
...
}
It will make PropertyAccessor to set new id value to Column object. The last one will throw exception as there is no way to set new id to Column (no setter, property is not public, etc).
Solution: To preserve key order. If you get data[columns][0][id]=1, data[columns][1][id]=2, data[columns][2][id]=3 and you delete first element you should send data[columns][1][id]=2, data[columns][2][id]=3
PS Key order preserving for Forms is good practice for all cases. It will prevent you from redundant UPDATE queries and loops.

'That is not a valid option' Error in custom formtype submit

is there an easy way to allow choice fields in symfony to validate correctly with data that was added via js? So for example you load an empty field then populate it with js/ajax calls then select one of the options an press submit, but the validator always throws this option is not valid errors...
To give some background, Ive got a custom form type that uses the choice type as a parent, and also a custom data transformer that converts the options into entity's (which I can confirm works because if I change the form type to text and manually enter the id corresponding to the choice I would want to select, the form submits fine).
Any idea's? Im happy to provide any files you might want to have a look at?
Edit nullstateType.php
<?php
namespace ISFP\Index\IndexBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use ISFP\Index\IndexBundle\Form\Transformer\nullstateTransformer;
use Doctrine\Common\Persistence\ObjectManager;
class nullstateType extends AbstractType
{
/**
* #var ObjectManager
*/
private $om;
/**
* #param ObjectManager $om
*/
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new nullstateTransformer($this->om);
$builder->prependNormTransformer($transformer);
}
public function setAllowedValues(OptionsResolverInterface $resolver)
{
return array( 'widget' => array('choice'));
}
public function getDefaultOptions(array $options)
{
return array(
'invalid_message' => 'The selected state does not exist',
'property_path' => false
);
}
public function getParent()
{
return 'choice';
}
public function getName()
{
return 'nullstate';
}
}
nullstateTransformer.php
<?php
namespace ISFP\Index\IndexBundle\Form\Transformer;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use ISFP\Index\IndexBundle\Entity\State;
class nullstateTransformer implements DataTransformerInterface
{
/**
* #var ObjectManager
*/
private $om;
/**
* #param ObjectManager $om
*/
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
/**
* Transforms an object (state) to a string (id).
*
* #param Issue|null $state
* #return string
*/
public function transform($state)
{
if (null === $state) {
return "";
}
return $this->om->getRepository('ISFPIndexEntityBundle:State')->getId();
}
/**
* Transforms a string (id) to an object (state).
*
* #param string $id
* #return Issue|null
* #throws TransformationFailedException if object (state) is not found.
*/
public function reverseTransform($id)
{
if (!$id) {
return null;
}
$state = $this->om
->getRepository('ISFPIndexEntityBundle:State')
->findOneById(intval($id))
;
if (null === $state) {
throw new TransformationFailedException(sprintf(
'An state with id "%s" does not exist!',
$id
));
}
return $state;
}
}

Categories