Symfony 4 map disabling not working - php

I'm trying to put two different entities (employee and contractor) in one selectbox (EntityType). So I created an unmapped entity called Receiver that puts all the loaded entities in one collection.
When debugging everything goes well, but as soon as it creates the form it gives me the following exception:
Class "App\Receiver\Receiver" seems not to be a managed Doctrine entity. Did you forget to map it?
And it indeed is not a managed Doctrine entity because it should only exist in the code. So in my type I've added the mapped => false option, however it still gives me that same exception.
Here is some code:
OrderController.php where the overall form is being built and a collection type is made
->add('orderNotes', CollectionType::class, [
'entry_type' => NotesType::class,
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'by_reference' => false,
'required' => false,
'label' => false,
'mapped' => false
])
And here is the NotesType Form
public function buildForm(FormBuilderInterface $builder, array $options)
{
$options['mapped'] = false;
$data = array_merge($data, Receiver::loadData($this->entityManager->getRepository("App:Contractor")->findAll(), "name", "id"));
$data = array_merge($data, Receiver::loadData($this->entityManager->getRepository("App:Employee")->findAll(), "name", "id"));
$builder
->add('body', TextareaType::class, ['attr' => ['class' => 'form-control']])
->add('receiver', EntityType::class, [
'class' => Receiver::class,
'data' => $data,
'choice_label' => 'name',
'choice_value' => "value",
'placeholder' => '- Selecteer -',
'required' => false,
'mapped' => false,
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => WorkorderNote::class,
'mapped' => false,
]);
parent::configureOptions($resolver);
}
So I have changed mapped to false about everywhere I know. So if you could please help me with this weird problem I would be very glad.
Kind regards

Related

Cannot read index "type" from object of type "stdClass" because it doesn't implement \ArrayAccess

I am getting this error on this
if ($this->container->getParameter('sso.so') === true) {
$builder->add('familyMembers', CollectionType::class, array(
'type' => new FamilyMember(),
'allow_add' => TRUE,
'allow_delete' => TRUE,
'by_reference' => FALSE,
));
$builder->get('familyMembers')->setData(array());
}
this is the form Type
class FamilyMember extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('type', ChoiceType::class, array(
'label' => ' ',
'required' => FALSE,
'choices' => array(
'SP' => 'account.address.option.type.SP',
'DP' => 'account.address.option.type.DP',
),
'expanded' => TRUE,
'multiple' => FALSE,
'placeholder' => FALSE,
))
what I am trying to do is allow the form to be created if they meet that condition.
this worked but i updated to symfony2.8 and I also went from guzzle3 to guzzle 6 (doubt is this one)
According to documentation starting from Symfony 2.8 entry_type replaces type.
$builder->add('familyMembers', CollectionType::class, array(
'entry_type' => new FamilyMember(),
'allow_add' => TRUE,
'allow_delete' => TRUE,
'by_reference' => FALSE,
));

Symfony embedded ChoiceType form updating every entity instance

I have an EditAnnouncementType form which is embedded in a CollectionType form. The embedded form has two ChoiceType forms, one which properly updates the mapped Announcement entity. The other one however, will attempt to update all instances of the entity in my database, resulting in this error.
Type error: Argument 1 passed to AppBundle\Entity\Announcement::setType() must be of the type integer, null given, called in /Users/dperezpe/dev/grand-central/673/grand-central/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php on line 528
EditAnnouncementType.php The type form is the error one.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('edit', SubmitType::class,
array
(
'label' => 'Save changes',
'attr' => ['class' => 'btn btn-primary']
))
->add('type', ChoiceType::class,
[
'choices' =>
[
'info_type' => 1,
'star_type' => 2,
'alert_type' => 3,
'lightbulb_type' => 4,
'event_type' => 5,
'statement_type' => 6,
'cat_type' => 7,
'hands_type' => 8
],
'expanded' => true,
'multiple' => false,
'required' => true,
'label_attr' => array(
'class' => 'sr-only'
),
])
->add('audience', ChoiceType::class,
[
'choices' =>
[
'Students: anybody with a student level field populated' => 'students',
'Employees: anybody with an employee ID number' => 'employees'
],
'expanded' => true,
'required' => true,
'multiple' => true
])
The CollectionType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('announcements', CollectionType::class,
[
'entry_type' => EditAnnouncementType::class,
'entry_options' => ['label' => false],
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => AnnouncementManager::class
]);
}
I suspect it is related to the difference in the HTML name that was rendered to this, where the type inputs are missing an empty []
<input type="radio"
id="announcement_edit_collection_announcements_221_type_0"
name="announcement_edit_collection[announcements][221][type]"
required="required" value="1">
<input type="checkbox" id="announcement_edit_collection_announcements_221_audience_0"
name="announcement_edit_collection[announcements][221][audience][]
"value="students">

Symfony form validate An invalid form control with name='' is not focusable

I have for with fields type entity, drop down choice and required true but when submit form have error in console
An invalid form control with name='inbound_invoice_row[costObject]' is not focusable.
new:1 An invalid form control with name='inbound_invoice_row[accountingAccount]' is not focusable.
new:1 An invalid form control with name='inbound_invoice_row[user]' is not focusable.
Another field validate fine, like vat or price but for accountingAccount user costObject have this error in console
why not understand
my form
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('location', EntityType::class, [
'class' => Location::class,
'empty_value' => 'select_default_value',
'query_builder' => self::getLocations(),
'required' => false,
'label' => 'locations',
'translation_domain' => 'invoicing'
])
->add('costObject', EntityType::class, [
'class' => CostObject::class,
'empty_value' => 'select_default_value',
'choices' => self::getCostObjectHierarchy(),
'required' => true,
'label' => 'cost_object',
'translation_domain' => 'invoicing'
])
->add('accountingAccount', EntityType::class, [
'class' => AccountingAccount::class,
'empty_value' => 'select_default_value',
'query_builder' => self::getAccountingAccount(),
'required' => true,
'label' => 'accounting_account',
'translation_domain' => 'invoicing'
])
->add('user', EntityType::class, [
'class' => User::class,
'empty_value' => 'select_default_value',
'choices' => self::getR(),
'required' => true,
'label' => 'employee',
'translation_domain' => 'invoicing'
])
->add('description', TextType::class, [
'label' => 'description',
'required' => false,
'translation_domain' => 'invoicing'
])
->add('vat', ChoiceType::class, [
'choices' => $this->vatClasses,
'required' => true,
'label' => 'vat',
'translation_domain' => 'common'
])
->add('price', TextType::class, [
'label' => 'price',
'required' => true,
'translation_domain' => 'invoicing'
]);
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'EconomyBundle\Entity\InboundInvoiceRow',
'locations' => [],
'employees' => [],
'accounts' => [],
'vat' => [],
'cost' => [],
'ajax' => true,
'csrf_protection' => true
));
}
public function getName()
{
return 'inbound_invoice_row';
}
create form in action
$form = $this->createForm(
$this->get('economy.form.type.in_bound_invoice_row'),
$inboundInvoiceRow,
[
'validation_groups' => [InboundInvoiceRow::GROUP_POST],
'cascade_validation' => true,
'action' => $this->generateUrl('inbound_invoices_row_create', ['id' => $inboundInvoice->getId()]),
'method' => 'POST',
]
);
$form->add('submit', 'submit', array('label' => 'save', 'translation_domain' => 'invoicing'));
You probably have some js library that is used when rendering those fields (e.g. Select2 or Chosen). When there's some HTML validation error (e.g. the field is required but there is no value) on a field, but it's not visible - it might have display property set to none - then the browser is unable to attach error message to that field. This is what most likely triggers your error.
Simplest solution is to set 'required' => false in form type options and rely on backend validation (e.g. using Symfony Validation component) rather than on basic HTML validation.

Nested CollectionType Save Entity in ArrayCollection

i want to store some data
class Offer
{
/**
* #ORM\Column(type="array")
*/
private $meterPoints;
public function __construct()
{
$this->meterPoints = new ArrayCollection();
}
}
for an offer as a CollectionType.
class OfferType extends AbstractType
{
$builder
->add('meterPoints', CollectionType::class, array(
'entry_type' => OfferMeterPointType::class,
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'prototype_name' => '__mp_name__',
))
}
In the OfferMeterPointType I also have an EntityType
class OfferMeterPointType extends AbstractType
{
$builder
->add('meterPoint', EntityType::class, array(
'attr' => array(
'class' => 'chosen-select'
),
'class' => 'AppBundle:MeterPoint',
'choice_label' => 'meterPoint',
))
->add('billData', CollectionType::class, array(
'label' => false,
'entry_type' => OfferBillType::class,
'allow_add' => true,
'allow_delete' => true,
'entry_options' => array(
'label' => false
)
));
}
Now when I persist that entity the whole AppBundle:MeterPoint object get serialized and not just the id. I kind of understand why doctrine does that but can I change it such that just the id will be stored?
Also when I want to edit an Offer
$offer = $em->getRepository('AppBundle:Offer')->findOneById(2);
$form = $this->createForm(OfferType::class, $offer);
i get an Exception
Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
I guess a solution would be to create an Entity for the OfferMeterPointType but I don't really want to do that. Because I allmost never need that data.
Update
I tried like martin suggested. now the exception is gone but it still saves the complete object
$meterPoints = $this->em->getRepository('AppBundle:MeterPoint')->findAll();
//dump($meterPoints);
$builder
->add('meterPoint', ChoiceType::class, array(
'label' => 'offerMeterPoint.meterPoint',
'attr' => array(
'class' => 'chosen-selesct',
'placeholder' => 'ob.to'
),
'choices' => $meterPoints,
'choice_label' => function($meterPoint) {
return $meterPoint->getMeterPoint();
},
'choice_value' => function($meterPoint) {
if($meterPoint === null){
return null;
}
dump($meterPoint);
return $meterPoint->getId();
},
'placeholder' => 'global.plz_select'
))
Update 2
Got it working
changed the ChoiceType
$meterPoints = $this->em->getRepository('AppBundle:MeterPoint')->findAll();
$mps = array();
foreach($meterPoints as $mp){
$mps [$mp->getMeterPoint()] = $mp->getId();
}
//dump($meterPoints);
$builder
->add('meterPoint', ChoiceType::class, array(
'label' => 'offerMeterPoint.meterPoint',
'attr' => array(
'class' => 'chosen-selesct',
'placeholder' => 'ob.to'
),
'choices' => $mps,
'placeholder' => 'global.plz_select'
))
You get a object serialized because your column type is array and EntityType automatically replaces choice values with objects.
There's however choice_value that accepts also a callable so I'd try fiddling with it and maybe you can get it to return just the id (maybe force string type?).
If this doesn't help then probably use just ChoiceType and handle the logic yourself.
This happens because Doctrine automatically deserializes the objects from $meterPoints that you try to use as entities with EntityType. These objects are obviously not managed by the Doctrine Entity manager. Thus the error.
I think you'll have to convert the $meterPoints to database entities before using $this->createForm(...) yourselves if you want to avoid creating more relations. Eventually and maybe even easier approach would be writing a custom Doctrine type that could do this for you:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/custom-mapping-types.html

Split form field of entity property into several subfields with FormBuilder

I have one superclass which gets extended by two entities. The superclass has a N:M relation with another entity. In the formbuilder of the latter, I need to separate the two subtypes into excluding separate fields.
This is its FormType::buildForm method:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('options_subtype_1', 'entity', [
'class' => 'AcmeExampleBundle:Options',
'expanded' => true,
'multiple' => true,
'property_path'=> 'options',
'query_builder' => /* specific filter 1 */
])
->add('options_subtype_2', 'entity', [
'class' => 'AcmeExampleBundle:Options',
'expanded' => true,
'multiple' => true,
'property_path'=> 'options',
'query_builder' => /* specific filter 2 */
])
;
}
However, no options are saved on form submission, except when I comment one of the two fields above (the one left is saved). I imagine setting property_path to the same property from two fields on the same form does not work.
How can I achieve this?
I'm still searching for the perfect solution by myself. For now I handle this kind of issues with a mapped hidden field and a PRE_SUBMIT Form Event. This could look like
FormType::buildForm
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('options_subtype_1', 'entity', [
'class' => 'AcmeExampleBundle:Options',
'expanded' => true,
'multiple' => true,
'mapped'=> false,
'data' => $builder->getData()->getOptions(),
'query_builder' => /* specific filter 1 */
])
->add('options_subtype_2', 'entity', [
'class' => 'AcmeExampleBundle:Options',
'expanded' => true,
'multiple' => true,
'mapped' => false,
'data' => $builder->getData()->getOptions(),
'query_builder' => /* specific filter 2 */
])
->add('options', 'entity', [
'class' => 'AcmeExampleBundle:Options',
'required' => false,
'multiple' => true,
'attr' => ['style' => 'visibility: hidden;'],
'label' => false
]);
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) {
$data = $event->getData();
unset($data['options']);
$data['options'] = array_merge($data['options_subtype_1'], $data['options_subtype_2']);
$event->setData($data);
}
);
}

Categories