Symfony Form times out when trying to populate $form object - symfony

The below Symfony form works fine in development when I only have a few records of each entity in the database. However, once I connect it to an extract of my production database the page times out.
The size of the database tables in this extract are bigger (around 800 records each) but nothing to justify it timing out completely. I'm assuming that the problem is a misunderstanding of how best to populate $batch in
The controller:
public function batchInvoicesAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$members = $em->getRepository('AppBundle:Member')->findActiveMembers();
$batch = new InvoiceBatch();
foreach ($members as $member) {
$invoice = new Invoice();
$invoice->setMemberId($member);
$invoice->setSelected(True);
$invoice->setCreatedate(new \Datetime());
$invoice->setAmount($member->getDefaultinvoiceamount());
$invoice->setCurrency($member->getDefaultinvoicecurrency());
$invoice->setinvoicebatchid($batch);
$batch->addInvoiceId($invoice);
# exit(VarDumper::dump($batch));
}
$form = $this->createForm(InvoiceBatchType::class, $batch);
$form->handleRequest($request);
if ($form->isSubmitted() && ($form->isValid())) {
$batchform = $form->getData();
foreach ($batchform->getInvoiceids() as $invoiceform) {
if ($invoiceform->getSelected() == False) {
$batchform->removeInvoiceId($invoiceform);
} else {
$em->persist($invoiceform);
}
}
$em->persist($batchform);
$em->flush();
return $this->redirectToRoute('view_monthly_invoices');
}
return $this->render('invoices/new.batch.invoice.html.twig', array(
'page_title' => 'Invoices',
'message' => 'Batch loading of invoices',
'form' => $form->createView(),
));
}
The repository function code is:
public function findActiveMembers()
{
return $this->getEntityManager()
->createQuery
(
'SELECT m
FROM AppBundle:Members m
WHERE m.active= :active
ORDER BY m.familyname1, m.familyname2, m.firstname'
)
->setParameter('active' ,true)
->getResult();
}
In case it's of any help:
1. Vardump of the partial $batch:
{#1022 ▼
#id: null
#invoice_ids: ArrayCollection {#1023 ▼
-elements: array:1 [▼
0 => Invoice {#1024 ▼
#id: null
#invoicebatch_id: InvoiceBatch {#1022}
#member_id: Member {#1049 ▶}
#payment_ids: ArrayCollection {#1027 ▶}
#attendc_ids: ArrayCollection {#1025 ▶}
#attende_ids: ArrayCollection {#1044 ▶}
#bankreceipt: null
#aggregate_payment: 0
#selected: true
#amount: "0.00"
#currency: "S"
#invoicedate: null
#createdate: DateTime {#19571 ▶}
#modifydate: null
#billedmonth: null
#description: null
}
]
}
2. My custom formTypes - this may be the problem as I'm still trying to get my head around FormTypes. The page only has one InvoiceBatchType which has an array of Invoice_ids used as CollectionType with InvoiceForBulkType:
class InvoiceBatchType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('batchevent', TextType::class, array(
))
->add('invoice_ids', CollectionType::class, array(
'entry_type' => InvoiceForBulkType::class,
))
;
}
/* ... */
}
class InvoiceForBulkType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('selected', CheckboxType::class, array(
'label' => ' ',
'required' => false,
))
->add('member_id', EntityType::class, array(
'class' => 'AppBundle:Member',
'choice_label' => 'FullName',
'label'=>'Member',
'disabled'=>true,
)
)
->add('amount', TextType::class, array(
'label' => 'Amount',
))
->add('currency',ChoiceType::class, array(
'choices' => array('Soles' => 'S', 'Dollars' => 'D'),
'choices_as_values' => true,
))
->add('invoicedate', DateType::class, array(
'widget' => 'single_text',
'data' => new \DateTime('now'),
'format' => 'dd/MMM/yyyy',
'label' => 'Date of invoice',
'attr'=> array(
'class'=>'datepicker',
)
))
->add('description', TextType::class, array(
'required'=>false,
))
;
}
/*...*/
}

Related

Symfony Dynamic Form - Get file from embedded form gives NULL

I have a dynamic form which display/hide a FileType field depending on another field value (link).
When i'm trying to get the file in my controller, it always gives me NULL
My UserType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('familyStatus', ChoiceType::class, [
'label' => 'Statut de famille',
'label_attr' => [
'class' => 'fg-label'
],
'attr' => [
'class' => 'sc-gqjmRU fQXahQ'
],
'required' => true,
'choices' => [
'Married' => 'M',
'Single' => 'S'
]
]);
$formModifier = function (FormInterface $form, $status = null) {
if ($status === 'M') {
$form->add('familyInfo', FamilyInfoType::class);
}
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
$user = $event->getData();
$formModifier($event->getForm(), $user->getFamilyStatus());
}
);
$builder->get('familyStatus')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
$status = $event->getForm()->getData();
$formModifier($event->getForm()->getParent(), $status);
}
);
}
My FamilyInfoType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('partnerName', TextType::class, [
'label' => 'Nom du partenaire',
'label_attr' => [
'class' => 'fg-label'
],
'attr' => [
'class' => 'sc-gqjmRU fQXahQ'
],
'required' => true
])
->add('weddingProof', FileType::class, [
'label' => 'Acte de mariage',
'label_attr' => [
'class' => 'Upload-label'
],
'attr' => [
'class' => 'Upload-input',
'maxsize' =>'4M',
'accept' =>'image/*'
],
'required' => false,
'mapped' => false
]);
}
My UserController:
/**
* #Route("/user", name="add_user", methods={"GET", "POST"})
* #param Request $request
*/
public function addUser(Request $request) {
$response = [];
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if ($user->getFamilyStatus() === 'M') {
var_dump("ok");
$document = $form->get('familyInfo')->get('weddingProof')->getData();
$partnerName = $form->get('familyInfo')->get('partnerName')->getData();
var_dump($document); // NULL
var_dump($partnerName); // OK the value is displayed
die;
}
}
return $this->render("user/registration.html.twig", ['form' => $form->createView()]);
}
It's working with TextType field but not with FileType. What's wrong with my form.
The issue is with the mapped => false option to the file type. The form is not setting the uploaded file object in the property of your entity because it’s not mapped.

Pass array of data to form

I'm using symfony and I need to pass two arrays so I can make a selectable list.
For now in form builder I have this:
->add('city', EntityType::class, [
'label' => 'Select city',
'class' => Cities::class,
'choice_label' => 'title',
'choice_value' => 'title'
])
It throws me all cities in the list. I want to filtrate them. I've done filtration on my controller like this:
$capitals = $cityRepository->findBy(['cityType' => CityType::capital()->id()]);
$villages = $cityRepository->findBy(['villageType' => CityType::village()->id()]);
this returns me two arrays: capitals and villages.
How can I pass them to the form ?
In your controller :
$form=$this->createForm(YourFormType::class, $yourEntity, array(
'capitals'=>$capitals,
'villages'=>$villages
));
In your form :
public function buildForm(FormBuilderInterface $builder, array $options) {
/** #var array $capitals */
$capitals=$options['capitals'];
/** #var array $villages */
$villages=$options['villages'];
$builder->add('city', EntityType::class, array(...)
->add('vallacap', ChoiceType::class, array(
'mapped'=>false, //Make sure it's not mapped to any entity
'choices'=>array(
'Capitals'=>$capitals,
'Villages'=>$villages
),
'required'=>false,
));
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class'=>Personnalisation::class,
'capitals'=>null, // Set default to null in case argument is not passed
'villages'=>null,
));
}
You need to pass the arrays to choices option.
https://symfony.com/doc/current/reference/forms/types/entity.html#using-choices
->add('city', EntityType::class, [
'label' => 'Select city',
'class' => Cities::class,
'choice_label' => 'title',
'choice_value' => 'title',
'choices' => $choices // ------------> This line
])
$choices = array_merge($capitals, $villages);

Field with query should not be blank

How do I add validation constraints "Field is required" in symfony2 PostType class? Any suggestions? I am new in SF2 and I'm just editing what has been done by previous developer.
use Symfony\Component\Validator\Constraints\NotBlank;
class BlogPostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$blogPostCategories = BlogPostCategoryQuery::create()
->filterByBlogPost($builder->getData())
->find();
$categoryIds = array();
foreach ($blogPostCategories as $blogPostCategory) {
$categoryIds[] = $blogPostCategory->getCategory()->getId();
}
$queryOptions = array(
'option_status' => Categorypeer::STATUS_ACTIVE,
'option_category_ids' => $categoryIds
);
$categories = CategoryQuery::create()
->filterActiveCategoriesByOptions($queryOptions)
->find();
$builder->add('category_ids', 'model', array(
'label' => 'Category',
'mapped' => false,
'class' => 'Deal\MainBundle\Model\Category',
'query' => CategoryQuery::create()
->filterActiveCategoriesByOptions()
->orderByName(),
'property' => 'name',
'empty_value' => 'Select categories',
'empty_data' => null,
'required' => true,
'multiple' => true,
'data' => $categories,
'constraints' => array(
new NotBlank(array(
'message' => 'Your message can not be blank! Ouch!'
)),
)
));
Thank you
You should set required => true for this type from the parent form when calling (that's the form type that uses your BlogPostType):
$formBuilder->add('whatever', BlogPostType::class, ['required' => true]);
Also, you could set required = true by default for BlogPostType:
class BlogPostType extends AbstractType
{
// ...
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'required' => true
]);
}
}
You can do it with constraints key. Like this:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('message', TextareaType::class, array(
'required' => true,
'constraints' => array(
new NotBlank(array(
'message' => 'Your message can not be blank! Ouch!'
)),
)
))
;
}
do not forget to add uses:
use Symfony\Component\Validator\Constraints\NotBlank;

Pre select Form with ready entity in Symfony2

want to pre select my form in Symfony.
I do it with the Form builder. It works except of the child table is not saving.
My Invoice Type
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('invoiceNumber', 'hidden', array('label' => ''))
->add('date', 'date', array('label' => 'Field', 'data' => new \DateTime("now")))
->add('PaidPrice', 'money', array('label' => 'Bereits bezahlt', 'attr' => array('class' => '')))
->add('invoicepos', 'collection', array(
'type' => new InvoiceposType(),
'allow_add' => true,
'allow_delete' => true,
'cascade_validation' => true,
'by_reference' => true,
))
;
}
My invoicepos Type
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('pos', 'text', array('label' => '', 'attr' => array()))
->add('quantity', 'hidden')
->add('price', 'hidden')
->add('tax', 'hidden')
;
}
My Controller to start the Form
public function newAction($id) {
$em->persist($entInvoice);
//$em->flush($entInvoice); //works perfect, but i dont want to save that, just pre select for the form
$form = $this->createCreateForm($entInvoice);
return array(
'entity' => $entInvoice,
'form' => $form->createView(),
);
}
Code when i submit the form
public function createAction(Request $request) {
$entity = new Invoice();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('pspiess_letsplay_invoice_show', array('id' => $entity->getId())));
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
The data is there, but with nor relation!
What did i wrong?
Thanks for help.
Found a solution for my problem.
Before i flush i add the child entity...
foreach ($entity->getInvoicepos() as $entInvoice) {
$entity->addInvoicepos($entInvoice);
}

Symfony 2: Set field as read only after first save

I have a Symfony 2 entity. When I create a new record, I must fill all the values using a form, but after saving it, one of the values, $amount shouldn't be updatable when I update the others members.
How can I accomplish this? It's possible to mark a form member as a read-only, in runtime?
By using the validation_groups and name options when creating your form, you can change the form.
The name attribute sets the form creation, and the validation_groups takes care of the validation.
For example, in the create/new method of your controller;
public function createAction(Request $request)
{
// Instantiate new Foo object
$client = new Foo();
// create the form (setting validation group)
$form = $this->formFactory->create('foo', $foo, array(
'name' => 'create',
'validation_groups' => array('create')
)
);
// form has been submitted...
if ('POST' === $request->getMethod()) {
// submits the form
$form->handleRequest($request);
// do validation
if ($form->isValid()) {
// do whatever
}
}
// either GET or validation failed, so show the form
return $this->template->renderResponse('FooBundle:foo:add.html.twig', array(
'form' => $form->createView(),
'foo' => $foo
));
}
And in the edit/update function of your controller;
public function updateAction($id, Request $request)
{
// Instantiate Client object
$client = new Foo($id);
// create the form (setting validation group)
$form = $this->formFactory->create('foo', $foo, array(
'name' => 'update',
'validation_groups' => array('update')
));
// form has been submitted...
if ('POST' === $request->getMethod()) {
// submits the form
$form->handleRequest($request);
// do validation
if ($form->isValid()) {
// do whatever
}
}
// either GET or validation failed, so show the form
return $this->template->renderResponse('FooBundle:foo/edit:index.html.twig', array(
'form' => $form->createView(),
'foo' => $foo
));
}
And your Form Type will look something like;
class FooType extends BaseAbstractType
{
protected $options = array(
'data_class' => 'FooBundle\Model\Foo',
'name' => 'foo',
);
private $roleManager;
public function __construct($mergeOptions = null)
{
parent::__construct($mergeOptions);
}
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->$options['name']($builder, $options);
}
private function create(FormBuilderInterface $builder, array $options)
{
// ID
$builder->add('Id', 'text', array(
'required' => true,
'label' => 'ID',
'attr' => array(
'placeholder' => 'Format: 2 alphanumeric (e.g. A1)'
)
));
// Name - only show on create
$builder->add('Name', 'text', array(
'required' => true,
'label' => 'Name',
'attr' => array(
'placeholder' => 'Your name'
)
));
// add the submit form button
$builder->add('save', 'submit', array(
'label' => 'Save'
));
}
private function update(FormBuilderInterface $builder, array $options)
{
// ID
$builder->add('Id', 'text', array(
'required' => true,
'label' => 'ID',
'attr' => array(
'placeholder' => 'Format: 2 alphanumeric (e.g. A1)',
)
));
// Name - just for show
$builder->add('Name', 'text', array(
'required' => true,
'label' => 'Name',
'attr' => array(
'readonly' => 'true' // stops it being editable
)
));
// add the submit form button
$builder->add('save', 'submit', array(
'label' => 'Save'
));
}
}
P.S. All my classes are declared as services, so how you call create forms/views/etc may be different.

Resources