Symfony Selection of Entity using Doctrine - php

i need some help.
I have a Form where i would like to either choose an existing Entity or submit a new one. So i have a Class Dolmetscher (Interpreter for languages) with title, name, surname and language. To create the Form i have a Class InterpreterType with the function
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('anrede', ChoiceType::class, array(
'choices' => array(
'Herr' => 'Herr',
'Frau' => 'Frau'
)
))
->add('vorname')
->add('nachname')
->add('sprache')
->add('dolmetscher', EntityType::class, array(
'class' => 'AppBundle:Dolmetscher',
'placeholder' => 'Dolmetscher wählen',
'label' => 'Dolmetscher',
'choice_value' => 'id',
'choice_label' => function ($dolmetscher) {
return $dolmetscher->getAnrede() . ' ' .
$dolmetscher->getVorname() . ' ' .
$dolmetscher->getNachname();
},
'mapped' => false,
))
->add('select', SubmitType::class, array(
'label' => 'Übernehmen',
'attr' => array(
'class' => 'btn btn-default',
'formnovalidate' => 'formnovalidate'
)
))
->add('save', SubmitType::class, array(
'label' => 'OK',
'attr' => array(
'style' => 'float: right',
'class' => 'btn btn-default'
)
))
->add('reset', SubmitType::class, array(
'label' => 'Zurücksetzen',
'attr' => array(
'style' => 'float: right; margin-right: 10px',
'class' => 'btn btn-warning',
'formnovalidate' => 'formnovalidate'
)
));
}
So i have a selection with Entities, which is working, with a 'select' Button and Form fields for a new Dolmetscher with a 'save' Button. Also a 'reset' Button
My Controller Class looks like
/**
* #Route("/u01/5", name="u1_5")
*/
public function dolmetscherAction(Request $request) {
$session = $this->get("session");
var_dump($session->get("foo"));
if (!$session->get("dolmetscher")) {
$dolmetscher = new Dolmetscher();
} else {
$dolmetscher = $session->get("dolmetscher");
}
$dolmetscherForm = $this->createForm(DolmetscherType::class, $dolmetscher);
$dolmetscherForm->handleRequest($request);
if ($dolmetscherForm->get('select')->isClicked()) {
$dolmetscher = $dolmetscherForm->get('dolmetscher');
$session->set("dolmetscher", $dolmetscher);
return $this->redirectToRoute('u1_5');
}
if ($dolmetscherForm->get('reset')->isClicked()) {
$dolmetscher = new Dolmetscher();
$session->set("dolmetscher", $dolmetscher);
return $this->redirectToRoute('u1_5');
}
if ($dolmetscherForm->get('save')->isClicked() && $dolmetscherForm->isSubmitted() && $dolmetscherForm->isValid()) {
$dolmetscher = $dolmetscherForm->getData();
$session->set("dolmetscher", $dolmetscher);
return $this->redirectToRoute('homepage');
}
return $this->render('urkunden/u01/5.html.twig', [
'form' => $dolmetscherForm->createView(),
'page_title' => 'U01'
]);
}
I want to put the Dolmetscher from the selection into $_SET for later use ,e.g. persist in DB, which works fine for a new Dolmetscher but not for my selection. I get an Exception
Serialization of 'Closure' is not allowed
I'm not sure if I'm doing this right at all (I have some OneToMany Relations and wanted to have a view for each Entity/Form and persist everything at once at the end so that i don't have only a Dolmetscher in my DB when the user quits in mid process)
I also thought it might be possible to populate the Form fields from the selection which I couldn't get to work. Can someone please help me, i would appreciate it.

This part of code is probably the origin of your problems :
if ($dolmetscherForm->get('select')->isClicked()) {
$dolmetscher = $dolmetscherForm->get('dolmetscher'); <------ this one
$session->set("dolmetscher", $dolmetscher);
return $this->redirectToRoute('u1_5');
}
you are trying to serialize a form object which contains a closure. Closure can not be serialized ( visit this link for more insights Exception: Serialization of 'Closure' is not allowed )
If you dump $dolmetscher variable you will probably get a form object not the entity you want. try to replace the line :
$dolmetscher = $dolmetscherForm->get('dolmetscher');
with :
$dolmetscher = $dolmetscherForm->get('dolmetscher')->getData();

Related

Symfony 419 status error on AJAX form post

I was posting a Symfony form via AJAX post and after I made a field edit on my "Siparis" entity and related form field in "SiparisType" I keep getting 419 on post.
Symfony version: 6.0.2 - PHP version:8.1.2 Database: 10.4.22-MariaDB
I tried to disable csrf protection and still getting the same status 419 and nothing else.
Symfony route to handle AJAX post(I reverted my latest changes after editing the field below version was working fine earlier):
#[Route('/save/', name: 'save', methods: ['POST'])]
public function save_siparis(Request $request, EntityManagerInterface $entityManager): JsonResponse
{
$siparis = new Siparis();
try {
$form = $this->createForm(SiparisType::class, $siparis);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($siparis);
$entityManager->flush();
return new JsonResponse(['result' => 'OK', 'siparis_id' => $siparis->getId()]);
}
}catch(\Exception $e){
error_log($e->getMessage());
return new JsonResponse(array('result' => $e->getMessage()), 419);
}
}
Render Form route on Controller:
Only change is: 'firma' => $id option for form in this section
#[Route('/new/{id}', name: 'new', methods: ['GET'])]
public function new($id, Request $request, EntityManagerInterface $entityManager, SiparisRepository $siparisRepository,FirmaRepository $firmaRepository, IlgiliRepository $ilgiliRepository): Response
{
$siparis = new Siparis();
$latest_siparis = $siparisRepository->findBy(['Musteri' => $id], ['id' => 'desc', ]);
$siparis_id = 1;
if(!is_null($latest_siparis))
$siparis_id = count($latest_siparis) + 1;
$musteri = $firmaRepository->find($id);
$siparisNo = 'TST-'.str_replace(' ', '-',$musteri->getKod()).'-'.str_pad($siparis_id, 3, '0', STR_PAD_LEFT);
$form = $this->createForm(SiparisType::class, $siparis, ['firma' => $id,'attr' => ['id' => 'siparis_form']]);
$firmalar = $firmaRepository->findBy(['Type' => 0]);
$maliyet = new Maliyetler();
$maliyet_form = $this->createForm(MaliyetlerType::class, $maliyet, ['attr' => ['id' => 'maliyet_form']]);
return $this->renderForm('siparis/new.html.twig', [
'siparisNo' => $siparisNo,
'sipari' => $siparis,
'form' => $form,
'maliyet_form' => $maliyet_form,
'satici_firmalar' => $firmalar,
'musteri' => $musteri,
'mode' =>'NEW'
]);
}
My FormType:
The field: 'siparis_veren' was a TextType and i have changed this one as a EntityType and fetched the related entities via query builder
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$firma = $options['firma'];
$SIPARIS_CHOICES = ['Devam Ediyor' => '1','Tamamlandı' => '2','İptal' => '3'];
$builder
->add('teslim_tarihi', DateType::class, [
'widget' => 'single_text',
'label' => 'Teslim Tarihi', 'attr' =>['class' => 'form-control', 'placeholder' => 'Teslim Tarihi']
])
->add('siparis_tarihi', DateType::class, [
'widget' => 'single_text',
'label' => 'Sipariş Tarihi', 'attr' =>['class' => 'form-control', 'placeholder' => 'Sipariş Tarihi']
])
->add('siparis_veren', EntityType::class,['class' => Ilgili::class,
'choice_label' => 'full_name',
'query_builder' => function (EntityRepository $er) use ($firma) {
return $er->createQueryBuilder('ilgili')
->andWhere('ilgili.firma = :firma')
->setParameter('firma', $firma);
},
'label' => 'Siparişi Veren', 'attr' =>['class' => 'form-control', 'placeholder' => 'Siparişi Veren']])
->add('siparis_durum', ChoiceType::class,['choices' => $SIPARIS_CHOICES,'attr' =>['class' => 'form-control', 'placeholder' => 'Siparişi Alan'] ])
->add('siparis_turu', HiddenType::class)
->add('siparis_genel_aciklama', TextType::class,['label' => 'Sipariş Genel Açıklaması', 'attr' =>['class' => 'form-control', 'placeholder' => 'Sipariş Genel Açıklaması']])
->add('siparis_satir_aciklama', HiddenType::class)
->add('siparis_miktari', HiddenType::class)
->add('siparis_fiyati', HiddenType::class)
->add('fatura_durumu', HiddenType::class)
->add('siparisNo', HiddenType::class)
->add('siparis_kdv_orani', HiddenType::class);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Siparis::class,
'csrf_protection' => true,
'csrf_field_name' => '_token',
]);
$resolver->setRequired(['firma']);
}
My AJAX form post on client side(No change here):
$('form[name="siparis"]').submit(function(e) {
e.preventDefault();
var url = "{{ path('siparis_save') }}";
var formSerialize = $(this).serialize();
$.post(url, formSerialize, function(response) {
if(response.result === "OK")
{
$( 'form[name="maliyetler"]' ).submit();
}
else
{
console.log(response.result);
}
}, 'JSON');
});
In my Siparis Entity siparis_veren was a text field and i added a ManyToOne relation with Ilgili class to it and after my changes post keep giving me 419 error.
#[ORM\ManyToOne(targetEntity: Ilgili::class, inversedBy: 'siparisler')]
#[ORM\JoinColumn(nullable: false)]
private $siparis_veren;
I tried clearing cache, removed related siparis_veren field from form type and controller but result is same unless I revert siparis_veren to TextType as it was before.
Sorry if my explanation is not enough, I couldn't find any results regarding this issue and SO is my only choice, I am a newbie in Symfony.
Thank you.
Okay found the issue, I didn't notice that I set status to 419 on Try Catch catch block so thought it was about Symfony or client side. After doing some debugging I get "An error has occurred resolving the options of the form "App\Form\SiparisType": The required option "firma" is missing." error which is caused by
SiparisConroller.php
$form = $this->createForm(SiparisType::class, $siparis);
This line in save_siparis() function. In SiparisType I have set 'firma' field as required
SiparisType.php
$resolver->setRequired(['firma']);
Therefore I got an error in Try Catch block.
Thanks to #jean-max for his advice to check Try Catch.

How get field value in form builder in Symfony

How to get field value in form builder in Symfony.
I have 2 Dropdowns in the form
I want to should the related option in Dropdown2 based on Dropdown1 in when the Page is Opening.
Here is My Form
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Event\DataEvent;
use C2Educate\ToolsBundle\Entity\Students;
public function buildForm(FormBuilder $builder, array $options) {
Field 1:
$builder->add('leadSource', 'entity', array(
'label' => 'How did you hear about C2? Source ',
'class' => 'C2EducateToolsBundle:LeadSources',
'query_builder' => function($repo) {
return $repo->createQueryBuilder('p')->orderBy('p.sort_order', 'ASC');
},
'property' => 'name',
'empty_value' => 'Select'
));
$leadSource = 1;
$leadSource = 1; - it works when I assign value statically, but I want to get the value of "leadSource" and assign it to $leadSource
I want to get the leadSource and pass it to leadSourceSub query
Field 2:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (DataEvent $event) {
$form = $event->getForm();
$entity = $event->getData();
$leadSource = $entity->getLeadSourceID();
$form->add('leadSourceSub', 'C2Educate\ToolsBundle\Entity\Students', array(
'label' => ' Source Detail ',
'required' => true,
'class' => 'C2EducateToolsBundle:LeadSourceSubs',
'query_builder' => function($repo) use ($leadSource) {
return $repo->createQueryBuilder('p')
->where('p.lead_source_id =:leadSource')
->setParameter('leadSource', $leadSource)
->orderBy('p.sort_order', 'ASC');
},
'property' => 'name',
'empty_value' => 'Select'
));
});
You cannot get form data from $builder, because... it's a form builder, not a form. It doesn't contain any data yet.
To make this work you need to make use of FormEvents. In this case, you probably will need FormEvents::PRE_SET_DATA event listener.
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
// in your case it's C2EducateToolsBundle:LeadSourceSubs
$entity = $event->getData();
$leadSource = $entity->getLeadSource();
// adding this field again will override it.
$form->add('leadSourceSub', 'entity', array(
'label' => ' Source Detail ',
'required' => true,
'class' => 'C2EducateToolsBundle:LeadSourceSubs',
'query_builder' => function($repo) use ($leadSource) {
return $repo->createQueryBuilder('p')
->where('p.lead_source_id =:leadSource')
->setParameter('leadSource', $leadSource)
->orderBy('p.sort_order', 'ASC');
},
'property' => 'name',
'empty_value' => 'Select'
));
}
});
Please note that this code is not tested and may need some validation like to check if $entity is what you expect it to be in any case.

Symfony2 set selected in EntityType

i have a problem when I would to set a default value in a select (selected="selected") in a form generated with Symfony 2 (2.8.9).
I have this code in my controller:
$news = new News();
$news->setCategory(1);
//create form
$form = $this->createForm(NewsType::class, $news);
And this in my FormType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('category', EntityType::class,
array(
'placeholder' => 'Choise',
'class' => 'AppBundle:NewsCat',
'choice_label' => 'name'
));
}
AppBundle:NewsCat create a list of id => name (ex: 1 => 'Sport', 2 => 'Politic', etc), and I want that when I setCategory(1) it should be seen "Sport" as selected="selected" in my select.
Now i see ever "Choise".
I have tried to search everywhere on the web, I hope you can help me :)
Thanks to all
HTML code screen
You need to use data option to set selected object. My example below.
$defaultTech = $company->getDefaultTech();
if ($company->getForceDefaultTech() && $defaultTech != null) {
$builder->add('tech', HiddenType::class, ['data' => $defaultTech->getId()]);
} else {
$builder->add('tech', EntityType::class, [
'class' => 'HelpBundle\Entity\UserAccount',
'choice_label' => 'displayName',
'data' => $defaultTech,
'query_builder' => function (EntityRepository $er) use ($company) {
$qb = $er->createQueryBuilder('ua');
return $qb
->where('ua.company = :company')
->andWhere('ua.techie = 1')
->setParameter('company', $company);
},
]);
}

Symfony2 collection Form uniquenes

I have a symfony2 main form, with a field what is a collection type of an other field, like a Product entity with multiple Tag, but these tag has a unique hash.
There is an eventListener attached to the main form. If I send a data to the form and I send a Tag along with this unique has, the unique constraint on the class will say, that that field has to be unique. This work good, but in this EventListener I'm search in the DB for this unique field and if it's the right one, I do an assign, I replace the post content with an entity from the DB.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('eventDate', 'datetime',array(
'widget' => 'single_text',
'format' => 'yyyy-MM-dd HH:mm',
'invalid_message' => 'Wrong datetime format. Please use like this: 2015-09-20 14:45:12',
))
->add('eventEnds', 'datetime', array(
'widget' => 'single_text',
'format' => 'yyyy-MM-dd HH:mm',
'invalid_message' => 'Wrong datetime format. Please use like this: 2015-09-20 14:45:12',
))
->add('tag','collection', array(
'type' => new TagType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'prototype' => true,
'property_path' => 'professional',
'label' => false,
'options' => array(
'professional' => true,
),
))
->addEventListener(FormEvents::SUBMIT, [$this, 'submit'])
;
}
public function preSubmit(FormEvent $event)
{
/** #var MainForm $data */
$data = $event->getData();
foreach ($data->getTags() as $tag) {
if ($tag->getId() == null && $tag->getHash()){
$tagDB = $this->entityManager
->getRepository('ApplicationBundle:Tag')
->findOneBy([
'hash' => $professional->getHash(),
]);
if ($tagDB) {
$data->removeTag($tag);
$data->addTag($tagDB);
}
}
}
$event->setData($data);
}
If I dump the $data value after the setData, I see there the entities from the DB, but I still got a Unique validation error and I check in the validator, symfony pass in the original POST content.
Why is it like that and how can I solve this problem?
Should be
->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'submit'])
(PRE_SUBMIT instead of SUBMIT)
Your code should be something like:
public function preSubmit(FormEvent $event)
{
/** #var MainForm $data */
$data = $event->getData();
$num = count($data['tag']);
for ($i=0;$i<$num;$i++) {
$tag = $data['tag'][$i];
if (!isset($tag['id']) && isset($tag['hash'])){
$tagDB = $this->entityManager
->getRepository('ApplicationBundle:Tag')
->findOneBy([
'hash' => $tag['hash'],
]);
if ($tagDB) {
unset($data['tag'][$i]);
$data['tag'][$i] = array (
'id' => $tagDB->getId();
'hash' => $tagDB->getHash();
);
}
}
}
$event->setData($data);
}
Not sure the code is 100% correct as I have not been able to test it, but you get the idea.

magento saveAction - for beginners

I am a Magento beginner so please bear with me...
I am creating a simple extension for my site to add a custom field to my Tags in adminhtml. The custom field is just a number which I need to identify a specific Z-block (cms block extension) so that I can access it as a widget and show it on the frontend in the Tag "category".
I have created a custom module which is working: I set a field in the form using $fieldset and have extended TagController.php, both of which are being used (I made a simple trial to see whether or not they had been recognized). However, I do not know how to go about saving my custom field to DB (whether amending saveAction is enough, and I haven't done it properly, or if I need to add a custom Model or sql install).
Sorry for the "basic" question but I'm new at this, and have mostly done frontend dev (so my extension knowledge is simply limited).
Thank you to anyone who can help...
Claudia
NEW TAG FORM:
public function __construct()
{
parent::__construct();
$this->setId('tag_form');
$this->setTitle(Mage::helper('tag')->__('Block Information'));
}
/**
* Prepare form
*
* #return Mage_Adminhtml_Block_Widget_Form
*/
protected function _prepareForm()
{
$model = Mage::registry('tag_tag');
$form = new Varien_Data_Form(
array('id' => 'edit_form', 'action' => $this->getData('action'), 'method' => 'post')
);
$fieldset = $form->addFieldset('base_fieldset',
array('legend'=>Mage::helper('tag')->__('General Information')));
if ($model->getTagId()) {
$fieldset->addField('tag_id', 'hidden', array(
'name' => 'tag_id',
));
}
$fieldset->addField('form_key', 'hidden', array(
'name' => 'form_key',
'value' => Mage::getSingleton('core/session')->getFormKey(),
));
$fieldset->addField('store_id', 'hidden', array(
'name' => 'store_id',
'value' => (int)$this->getRequest()->getParam('store')
));
$fieldset->addField('name', 'text', array(
'name' => 'tag_name',
'label' => Mage::helper('tag')->__('Tag Name'),
'title' => Mage::helper('tag')->__('Tag Name'),
'required' => true,
'after_element_html' => ' ' . Mage::helper('adminhtml')->__('[GLOBAL]'),
));
$fieldset->addField('zblock', 'text', array(
'name' => 'zblock_id',
'label' => Mage::helper('tag')->__('Z-Block Id'),
'title' => Mage::helper('tag')->__('Z-Block Id'),
'required' => true,
'after_element_html' => ' ' . Mage::helper('adminhtml')->__('[GLOBAL]'),
));
$fieldset->addField('status', 'select', array(
'label' => Mage::helper('tag')->__('Status'),
'title' => Mage::helper('tag')->__('Status'),
'name' => 'tag_status',
'required' => true,
'options' => array(
Mage_Tag_Model_Tag::STATUS_DISABLED => Mage::helper('tag')->__('Disabled'),
Mage_Tag_Model_Tag::STATUS_PENDING => Mage::helper('tag')->__('Pending'),
Mage_Tag_Model_Tag::STATUS_APPROVED => Mage::helper('tag')->__('Approved'),
),
'after_element_html' => ' ' . Mage::helper('adminhtml')->__('[GLOBAL]'),
));
$fieldset->addField('base_popularity', 'text', array(
'name' => 'base_popularity',
'label' => Mage::helper('tag')->__('Base Popularity'),
'title' => Mage::helper('tag')->__('Base Popularity'),
'after_element_html' => ' ' . Mage::helper('tag')->__('[STORE VIEW]'),
));
if (!$model->getId() && !Mage::getSingleton('adminhtml/session')->getTagData() ) {
$model->setStatus(Mage_Tag_Model_Tag::STATUS_APPROVED);
}
if ( Mage::getSingleton('adminhtml/session')->getTagData() ) {
$form->addValues(Mage::getSingleton('adminhtml/session')->getTagData());
Mage::getSingleton('adminhtml/session')->setTagData(null);
} else {
$form->addValues($model->getData());
}
$this->setForm($form);
return parent::_prepareForm();
}
NEW CONTROLLER:
public function saveAction()
{
if ($postData = $this->getRequest()->getPost()) {
if (isset($postData['tag_id'])) {
$data['tag_id'] = $postData['tag_id'];
}
$data['name'] = trim($postData['tag_name']);
$data['zblock'] = $postData['zblock_id'];
$data['status'] = $postData['tag_status'];
$data['base_popularity'] = (isset($postData['base_popularity'])) ? $postData['base_popularity'] : 0;
$data['store'] = $postData['store_id'];
if (!$model = $this->_initTag()) {
Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Wrong tag was specified.'));
return $this->_redirect('*/*/index', array('store' => $data['store']));
}
$model->addData($data);
if (isset($postData['tag_assigned_products'])) {
$productIds = Mage::helper('adminhtml/js')->decodeGridSerializedInput(
$postData['tag_assigned_products']
);
$model->setData('tag_assigned_products', $productIds);
}
try {
$model->save();
Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('The tag has been saved.'));
Mage::getSingleton('adminhtml/session')->setTagData(false);
if (($continue = $this->getRequest()->getParam('continue'))) {
return $this->_redirect('*/tag/edit', array('tag_id' => $model->getId(), 'store' => $model->getStoreId(), 'ret' => $continue));
} else {
return $this->_redirect('*/tag/' . $this->getRequest()->getParam('ret', 'index'));
}
} catch (Exception $e) {
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
Mage::getSingleton('adminhtml/session')->setTagData($data);
return $this->_redirect('*/*/edit', array('tag_id' => $model->getId(), 'store' => $model->getStoreId()));
}
}
return $this->_redirect('*/tag/index', array('_current' => true));
}
The custom field I'm trying to add is "zblock"...thanks and, again, bear with me! :)
First add the field in database table.
For example if you want to add in your custom table.
ALTER TABLE myCustomModuleTable ADD COLUMN 'myCustomField' int(10);
Thenafter, In your controller action take the model object of that table and set the field.
If you are adding data in existing table row:
$value = 6;
$rowInWhichIWantToSave = Mage:getModel('companyname/modulename')->load($rowId);
$rowInWhichIWantToSave->setData('myCustomField',$value)->save();
If you are adding a new row:
$value = 6;
$rowInWhichIWantToSave = Mage:getModel('companyname/modulename');
$rowInWhichIWantToSave->setData('myCustomField',$value)->save();
Hope this helps!!

Categories