Symfony2 Form field Entity with 170k of results - php

I have a form with a field of relationship entity.
The problem is that that entity tien a lot of records, over 170,000 and render the view form the server is saturated and no load.
What solutions are there to this?
This is the form field
->add('stream', 'genemu_jqueryselect2_entity', array(
'class' => 'AcmeBundle:Stream',
'property' => 'name',
'choice_label' => 'name',
'multiple' => false,
'required' => false,
'configs' => array(
'multiple' => false,
)
)
)
IMPORTANT
I found something.
Stream entity is related to another entity under a bidirectional one-to-one.
Doctrine is running a query for each record to grab the data from that relationship.
Is there any way to tell Doctrine to not spread relationships and take "real" data Stream entity?

If I correctly understand you, you shoud look to query_builder options what allow you to fetch Streams what sutisfy some condition. E.g.:
->add('stream', 'genemu_jqueryselect2_entity', array(
'class' => 'AcmeBundle:Stream',
'property' => 'name',
'choice_label' => 'name',
'multiple' => false,
'required' => false,
'configs' => array(
'multiple' => false,
)
'query_builder' => function (StreamRepository $repository) {
return $repository->findStreamsWhatSatisfySomeCondition();
}
)
you can use external parameters like:
'query_builder' => function (StreamRepository $repository) use ($param) {
}
Detailed info you can find in doc. Hope that will help find solution :)

Related

Symfony - Categories count with EntityType

I have a search form that gets Categories from database and shows each category name as a checkbox, it's retrieved via EntityType, i want to show count categories in front of the category name, i managed to count each one from the database and put the result in an array like this : $categCount[name] = count;
How can i show in front of each category name her count using EntityType ?
->add('categories', EntityType::class, ['class' => 'AppBundle:Categorie',
'choice_label' => 'name',
'multiple' => true,
'expanded' => true,
'required' => false,
])
Now. I`m not sure how your entity looks like but if you have the count in the same entity you can do something like:
->add('categories', EntityType::class, ['class' => 'AppBundle:Categorie',
'choice_label' => 'getNameWithCategoriesCount',
'multiple' => true,
'expanded' => true,
'required' => false,
])
and in your entity
public function getNameWithCategoriesCount(){
return $this->getName().' '.$this->getCount();
}
Alternatively(not tested) you can :
->add(
'categories',
EntityType::class,
[
'class' => 'AppBundle:Categorie',
'choice_label' => function ($category) use ($this-em) {
return $category->getDisplayName() $this->em->getRepo..()->getCount($category);
},
'multiple' => true,
'expanded' => true,
'required' => false,
]
)
NOTE: For this approach you need to declare your form as service and pass the entityManager

Symfony2 - QueryBuilder error message

So, I'm going to try and explain the problem I have here :)
Catchable Fatal Error: Argument 1 passed to AppBundle\Controller\MunkakController::AppBundle\Controller{closure}() must be an instance of AppBundle\Controller\EntityRepository, instance of Doctrine\ORM\EntityRepository given
This is the error message I get. This is the code that I try to run:
$formbe = $this->createFormBuilder($ujbeszab, ['attr' => ['id' => 'ujbeszabid']])
->setAction($this->generateUrl('uj-beszab', array('szabid' => $szabid)))
->setMethod('POST')
->add('munkatipusok', 'entity', array('class' => 'AppBundle:Munkatipusok', 'query_builder' => function(EntityRepository $rep) {
$qb = $rep->createQueryBuilder('u');
return $qb->orderBy('u.munkatipusok', 'ASC');
}, 'empty_value' => null, 'label' => "Munkatípus", 'required' => false))
->add('idopont', 'date', array('label' => "Időpontja", 'format' => 'yyyy.MM.dd', 'years' => range(date('Y') -10, date('Y') +10), 'required' => true))
->add('megjegyzes', 'textarea', array('label' => "Megjegyzés", 'required' => false))
->add('submit', 'submit', array('label' => 'Létrehozás'))
->getForm();
It has some Hungarian variable names, basicly I'm trying to add a job to a database. You have to select the job type from a dropdown, enter the date('idopont'), you can also add a comment('megjegyzes'). The job types come from a different table, they come from the 'munkatipusok' table. So, what i'm trying to do is to be able to filter the shown jobs. I know I could show all the job types and then remove them from the select field with javascript, but that is risky, in case jscript doesn't run on the computer. So I want to filter server side, with a QueryBuilder.

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

Adding a default value along with entity in form type of Symfony2

I am a totally new in symfony2. I met a situation which I can't solve till now.
I have a controller, formtype and eventsubscriber in my project. The form builds by binding the entities. In that case for a particular entity I need to add a default value along with an ID in one of the form fields. My form type is
$builder->add('breed', EntityType::class, array(
'label' => 'Breed',
'class' => 'AppBundle:Masters\Breed',
'placeholder' => '----Select Breed----',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('b')
->orderBy('b.sortOrder', 'DESC');
},
'choice_label' => 'breed',
));
$builder->addEventSubscriber(new BreedSubscriber($factory));
My Event Subscriber is
private function addBreed($form, $breedmasterId) {
$form->add($this->factory->createNamed('breed',EntityType::class,null, array(
'class' => 'AppBundle:Masters\Breed',
'placeholder' => '----Select Breed--------',
'choice_label' => 'breed',
'required' => TRUE,
'mapped' => false,
'query_builder' => function (EntityRepository $repository) use ($breedmasterId) {
$qb = $repository->createQueryBuilder('bm')
->where('bm.breed = :breedmasterId')
->setParameter('breedmasterId', $breedmasterId);
return $qb;
},
'auto_initialize' => false
)));
}
I need to add a default value such as "General" along with an "id" in the addBreed subscriber and it need to be validate on formsubmission. Thanks in advance for the help.
You can add the following 'data' key in the array you configure your form:
$builder->add('breed',null, array(
'label' => 'Breed',
'data' => 'Sih Tzu'
))

Access properties and methods of a class while configuring EntityType in Formbuilder::add()

I`ve got a dropdown list in my Symfony2 form like this:
$builder->add('categories','entity', array(
'class' => 'MyBundle:Myentity',
'property' => 'name',
'label' => 'Mylabel',
'expanded' => false,
'multiple' => false,
'label_attr' => array ( 'class' => 'control-label' ),
'attr' => array ( 'class' => 'form-control',
'placeholder' => 'Placeholder',
'title' => "Mytitle",
'data-toggle' => 'tooltip',
'data-myidfromDB' => '????',
'data-mynamefromDB'=>'????' etc. )));
So I am getting a list of MyBundle:Myentity objects and when I choose one I want to show all its properties (like ID, name, etc.) which are stored in my DB and described in Entity class, in different html data-* fields. If I select another one from the list I want to see all information related to my newly selected option in HTML (to change dynamically). Any ideas how to do that?
Since Symfony 2.7 you can set the option choice_attr to ChoiceType and set it a callable receiving the choice as an argument.
EntityType inherits this option and the choice in that case is the instantiated entity, so you can write something like :
$builder->add('categories','entity', array(
'class' => 'MyBundle:MyEntity',
'property' => 'name',
'label' => 'Mylabel',
'attr' => array('class' => 'form-control'),
'label_attr' => array('class' => 'control-label'),
'choice_attr' => function (\AppBundle\Entity\MyEntity $myEntity) {
return array(
'data-private-property' => $entity->getPrivateProperty(),
'data-some-value' => $entity->someMethod(),
);
},
);
You can't do that in easy way.
But you can put more information in select label.
Look on
http://symfony.com/doc/current/reference/forms/types/entity.html#choice-label
Yout can put here more field details and get it from your javascript.

Categories