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
}
Related
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.
I would like to create a google categories matching(first field categorie from database and second field a user autocomplete field from google categories) form where i have an entity CategoriesConfig :
private $id;
/**
* #var string
*
* #ORM\Column(name="category_site", type="string", length=100)
*/
private $categorySite;
/**
* #var string
*
* #ORM\Column(name="category_google", type="string", length=100)
*/
private $categoryGoogle;
In my Controller i tried this
/**
* #Route("/adminDashboard/categoriesMatching", name="googleShopping_categories")
* #Security("has_role('ROLE_SUPER_ADMIN')")
*/
public function categoriesMatchingAction(Request $request)
{
// create a task and give it some dummy data for this example
$idSite = $this->get('session')->get('_defaultWebSite')->getId();
$categories = $this->getDoctrine()->getRepository('DataSiteBundle:SiteCategory')->findBy(array('IdSite' => $idSite));;
$categories_config = new CategoriesConfig();
//var_dump($categories);exit;
$form = $this->createForm(new CategoriesConfigType($categories), $categories_config);
return $this->render('GoogleShoppingBundle:Default:categoriesMatching.html.twig', array(
'form' => $form->createView()
));
}
And my form type : CategoriesConfigType:
class CategoriesConfigType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
private $site_categories;
public function __construct ($site_categories) {
$this->site_categories = $site_categories;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
foreach($this->site_categories as $k => $categorie){
$builder
->add('categorySite')
->add('categoryGoogle');
}
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Sp\GoogleShoppingBundle\Entity\CategoriesConfig'
));
}
}
I would like to have as many categories rows as row fields(website itecategorie and google categorie)
The result is like that:
Thank you in advance!
Your loop on $this->categories is uneffective, because the elements you add have the same name each time (categorySite and categoryGoogle), so the FormBuilder replaces the form field each time, instead of adding another one.
However, if you want your form to handle a Collection of CategoryConfigs, you need to take a different approach.
1) Create a CategoriesConfigType (as you did), but who is responsible of only a single CategoriesConfig entity
class CategoriesConfigType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('categorySite')
->add('categoryGoogle');
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Sp\GoogleShoppingBundle\Entity\CategoriesConfig'
));
}
}
2) Then use CollectionType field to manipulate your form as a whole collection of CategoryConfigTypes:
class YourCollectionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('categoriesConfigs', CollectionType::class, array(
'entry_type' => CategoriesConfigType::class,
'entry_options' => array('required' => false)
);
}
}
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.
So I'm trying to create a registration form in Symfony 2 which contains my "Person" entity. The person entity has a one-to-many join, and I want the registration form to allow the user to select a single instance of this "Many" side of the join.
The structure is Users and Institutions. A user can have many institutions. I want a user to select a single institution at registration time (but the model allows for more later).
The basic structure is:
RegistrationType -> PersonType -> PersonInstitutionType
…with corresponding models:
Registration (simple model) -> Person (doctrine entity) -> PersonInstitution (doctrine entity, oneToMany relation from Person)
I tried to pre-populate an empty Person & PersonInstitution record in the RegistrationController but it gives me the error:
Expected argument of type "string or Symfony\Component\Form\FormTypeInterface", "TB\CtoBundle\Entity\PersonInstitution" given
(ok above has been fixed).
I've moved the code from my website to here below, trying to remove all the irrelevant bits.
src/TB/CtoBundle/Form/Model/Registration.php
namespace TB\CtoBundle\Form\Model;
use TB\CtoBundle\Entity\Person;
class Registration
{
/**
* #var Person
*/
private $person
private $termsAccepted;
}
src/TB/CtoBundle/Form/RegistrationType.php
namespace TB\CtoBundle\Form;
use TB\CtoBundle\Form\PersonType;
class RegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('person', new PersonType());
$builder->add('termsAccepted','checkbox');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TB\CtoBundle\Form\Model\Registration',
'cascade_validation' => true,
));
}
public function getName()
{
return 'registration';
}
}
src/TB/CtoBundle/Entity/Person.php
namespace TB\CtoBundle\Entity;
use TB\CtoBundle\Entity\PersonInstitution
/**
* #ORM\Entity()
*/
class Person
{
/**
* #var ArrayCollection
* #ORM\OneToMany(targetEntity="PersonInstitution", mappedBy="person", cascade={"persist"})
*/
private $institutions;
}
src/TB/CtoBundle/Form/PersonType.php
namespace TB\CtoBundle\Form;
class PersonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('institutions', 'collection', array('type' => new PersonInstitutionType()))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TB\CtoBundle\Entity\Person',
));
}
/**
* #return string
*/
public function getName()
{
return 'tb_ctobundle_person';
}
}
src/TB/CtoBundle/Entity/PersonInstitution.php
namespace TB\CtoBundle\Entity
/**
* PersonInstitution
*
* #ORM\Table()
* #ORM\Entity
*/
class PersonInstitution
{
/**
* #ORM\ManyToOne(targetEntity="Person", inversedBy="institutions", cascade={"persist"})
*/
private $person;
/**
* #ORM\ManyToOne(targetEntity="Institution", inversedBy="members")
*/
private $institution;
/**
* #ORM\Column(type="boolean")
*/
private $approved;
}
src/TB/CtoBundle/Form/PersonInstititionType.php
namespace TB\CtoBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class PersonInstitutionType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('approved')
->add('person')
->add('institution')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TB\CtoBundle\Entity\PersonInstitution'
));
}
/**
* #return string
*/
public function getName()
{
return 'tb_ctobundle_personinstitution';
}
}
src/TB/CtoBundle/Controller/Registration.php
namespace TB\CtoBundle\Controller;
class RegisterController extends Controller
{
/**
*
* #param Request $request
* #return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function registerAction(Request $request)
{
$registration = new Registration;
$person = new Person();
$institution = new PersonInstitution();
$person->addInstitution($institution);
$registration->setPerson($person);
// this causes error:
// Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
// $institution->setPerson($person);
$form = $this->createForm(new RegistrationType(), $registration);
$form->handleRequest($request);
if($form->isValid()) {
$registration = $form->getData();
$person = $registration->getPerson();
// new registration - account status is "pending"
$person->setAccountStatus("P");
// I'd like to get rid of this if possible
// for each "PersonInstitution" record, set the 'person' value
foreach($person->getInstitutions() as $rec) {
$rec->setPerson($person);
}
$em = $this->getDoctrine()->getManager();
$em->persist($person);
$em->flush();
}
return $this->render('TBCtoBundle:Register:register.html.twig', array('form' => $form->createView()));
}
}
Here is a detailed solution for adding an Collection field to Person entity and formType.
Your complex question with Registration entity can be solved with this.
I suggest you to use this 3 entity related connection if it is really needed. (only because of termsAccepted data!?)
If you won't change your opinion, then use this annotation:
Registration code:
use TB\CtoBundle\Entity\Person;
/**
* #ORM\OneToOne(targetEntity="Person")
* #var Person
*/
protected $person;
Person code:
use TB\CtoBundle\Entity\PersonInstitution;
/**
* #ORM\OneToMany(targetEntity="PersonInstitution", mappedBy = "person")
* #var ArrayCollection
*/
private $institutions;
/* I suggest you to define these functions:
setInstitutions(ArrayCollection $institutions),
getInstitutions()
addInstitution(PersonInstitution $institution)
removeInstitution(PersonInstitution $institution)
*/
PersonInstitution code:
use TB\CtoBundle\Entity\Person;
/**
* #ORM\ManyToOne(targetEntity="Person", inversedBy="institutions", cascade={"persist"}))
* #var Person
*/
private $person;
PersonType code:
use TB\CtoBundle\Form\PersonInstitutionType;
->add('institutions', 'collection', array(
'type' => new PersonInstitutionType(), // here is your mistake!
// Other options can be selected here.
//'allow_add' => TRUE,
//'allow_delete' => TRUE,
//'prototype' => TRUE,
//'by_reference' => FALSE,
));
PersonController code:
use TB\CtoBundle\Entity\Person;
use TB\CtoBundle\Entity\PersonInstitution;
/**
* ...
*/
public funtcion newAction()
{
$person = new Person;
$institution = new PersonInstitution;
$institution->setPerson($person);
$person->addInstitution($institution);
$form = $this->createForm(new PersonType($), $person); // you can use formFactory too.
// If institution field is required, then you have to check,
// that is there any institution able to chose in the form by the user.
// Might you can redirect to institution newAction in that case.
return array( '...' => $others, 'form' => $form);
}
If you need more help in twig code, then ask for it.
I have a dynamic form in symfony. currently i have a external service where the data exist this services provided a way to render a form for data but i need integrate with my bussines logic into my app.
for solve this problem I implements a annotation and a CustomType. the annotation is simple holder for the name of the table in the external service
in my app i have a entity
/**
* Person
*
* #ORM\Table("person")
* #ORM\Entity
* #EService("person_data")
*/
class Person extends AbstractEntityEService
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**/
}
/**
* AbstractEntityEService
*
*/
abstract AbstractEntityEService
{
/**
* #var integer
*
* #ORM\Column(name="uuid", type="string")
*/
protected $uuid;
/**
* Holder for the data
protected $data;
/* setters and getters... */
}
the external service provide a uuid when i store data, with this uuid i can print the fields in my view and with this uuid i can update the data.
here is my CustomType
class ExternalType extends AbstractType {
/**
* #var Reader
*/
private $reader;
/**
* #var ExternalService
*/
private $ts;
public function __construct(Reader $reader, ExternalService $ts){
$this->reader = $reader;
$this->ts = $ts;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function(FormEvent $event) use ($options) {
$annotation = $this->reader->getClassAnnotation(
new \ReflectionClass($options['class']),
'MyBundle\Lib\Annotation\EServiceAnnotation'
);
// this is only form a empty form
if (null === $event->getData()) {
// here get the annotated value from entity and get a uuid
$event->setData($this->ts->getForm($annotation->getformName()));
}
$event->getForm()->getParent()->add('data', 'collection', array(
'allow_add' => true,
'label' => false
));
});
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver
->setDefaults(array(
'required' => false,
'error_bubbling' => true
))
->setRequired(array(
'class',
));
}
/**
* #inheritdoc
*/
public function getName()
{
return 'external';
}
/**
* #inheritdoc
*/
public function getParent()
{
return 'hidden';
}
}
this is the template for the CustomType
{% block external_widget %}
{% spaceless %}
<div data-form-name="{{ form.parent.vars.name }}" data-form-uuid="{{uuid}}"></div>
{% set type = type|default('hidden') %}
{{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock external_widget %}
i register my ExternalType like service for use into my main form PersonType
class AsociacionType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('uuid', 'external', array('class' => $options['data_class']));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MyBundle\Entity\Person'
));
}
/**
* #return string
*/
public function getName()
{
return 'my_bundle_person';
}
}
and at the last i use the doctrine.event_subscriber
postLoad : for fill the data property in my Entities using the uuid for call external service
prePersist: for persist the data sent by users into the external service
preUpdate: for update the data sent by user into the external service
Here the events
public function postLoad(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if ($entity instanceof AbstractEntityEService && null !== $entity->getUuid())
{
$t = $this->externalService->get($entity->getUuid());
$entity->setData((array)$t->getData());
}
}
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if ($entity instanceof AbstractEntityEService) {
$t = $this->externalService->persist($entity->getData(), $entity->getUuid());
$entity->setUuid($t->getUuid());
}
}
public function preUpdate(LifecycleEventArgs $args)
{
$this->prePersist($args);
}
The new and create works fine. but when i'm going to update the data for a unknown reason the preUpdate event never is called. I think it is because the form does not mean that the data has changed. I need to know how to tell to Symfony the form has changed