Problems with rendering the results of searching in Symfony 5.4 - symfony

I've recently started learning Symfony (from Documentation and Google;) so I have a lot of problems.
I want to search for games according to selected attributes (name, category, age, number of players, price, deposit). In SearchController I've created a form and in Game (Gra) Repository I built a QueryBuilder which I am trying to call in SearchController and render to search/result.twig.html
I am probably making a lot of mistakes, I try to fix them one by one, the last one is this:
Method name must be a string in this verse:
$ Games = $ this -> $ repository (Game :: class) -> findByField ($ Name, $ id_Category, $ Number of players, $ Age_of_years, $ Price, $ Deposit);
Is this because some of the fields are int? But anyway, even if I changed it to string, I can't render it ...
There are a lot of people with experience here, so I count on your help :)
MY GRA GAMEREPOSITORY
public function findByExampleField(?string $Nazwa,string $id_Kategoria,string $Liczba_graczy,string $Wiek_od_lat, int $Cena, int $Kaucja)
{
$qb = $this->createQueryBuilder('a')
->andwhere('a.Nazwa = :Nazwa')
->orWhere('a.id_Kategoria = :Kategoria')
->orWhere('a.Liczba_graczy = :Liczba graczy')
->orWhere('a.Wiek_od_lat = :Wiek od lat')
->orWhere('a.Cena = :Cena')
->orWhere('a.Kaucja = :Kaucja')
->setParameter(':Nazwa', $Nazwa)
->setParameter(':Kategoria', $id_Kategoria)
->setParameter(':Liczba graczy', $Liczba_graczy)
->setParameter(':Wiek od lat', $Wiek_od_lat)
->setParameter(':Cena', $Cena)
->setParameter(':Kaucja', $Kaucja);
$query = $qb->getQuery();
return $query->execute();
}
MY SEARCHCONTROLLER
{
#[Route('/search', name: 'app_search')]
public function searchAction(Request $request, GraRepository $repository, string $Nazwa='Nazwa',string $id_Kategoria="Kategoria",string $Liczba_graczy='Liczba_graczy',string $Wiek_od_lat ='Wiek_od_lat', string $Cena = 'Cena', string $Kaucja = 'Kaucja'):Response
{
$form = $this->createFormBuilder([])
->add('Nazwa', EntityType::class, ['required' => false, 'label' => 'Nazwa gry:', 'class' => Gra:: class ] )
->add('id_Kategoria', EntityType::class, ['required' => false, 'label' => 'Kategoria:', 'class' => Kategoria:: class])
->add('Liczba_graczy', EntityType::class, ['required' => false, 'label' => 'Liczba graczy:', 'class' => Gra:: class,'choice_label' => 'Liczba_graczy','expanded' => true, 'multiple'=> false,
'query_builder' => function (GraRepository $repository)
{
return $repository
->createQueryBuilder('l')
->select('l')
->groupBy('l.Liczba_graczy');
} ])
ADDING A FEW MORE FIELDS (...)
} ])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
$form = $request->request->get('Nazwa', 'id_Kategoria', 'Liczba_graczy', 'Wiek_od_lat', 'Cena', 'Kaucja');
$Gry=$this->$repository(Gra::class)-> findByField ($Nazwa,$id_Kategoria,$Liczba_graczy,$Wiek_od_lat, $Cena, $Kaucja);
if (!$Gry) {
throw $this->createNotFoundException(
'Taka gra nie istnieje'
);
}
return $this->render('search/result.html.twig', ['Gry' => $Gry]);
}
return $this->render('search/advsearch.html.twig', ['form' => $form->createView()]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Gra::class,
]);
}
}

Related

custom form to accept only specific email address FOSUserBundle 2.0/ Symfony3

I try to learn to create a website with Symfony 3.1.10. To help me on my project to create login/register, i decided to use the bundle "FOSUserBundle 2.0". So for now i create a Custom form (i changed the username field by name field). For my project, i tried to allow to register only user with a specific email address. So after few research, they explain to create custom behaviour, FOSUserbundle created Events. So when i have i REGISTRATION_SUCCESS, i create custom event listener as you can see below.
class CheckEmailBefore implements EventSubscriberInterface {
private $router;
private $request;
public function __construct(RouterInterface $router,Request $request)
{
$this->router = $router;
$this->request = $request;
}
public static function getSubscribedEvents() {
return [
FOSUserEvents::REGISTRATION_SUCCESS => 'onCheck'
];
}
/**
* #param FormEvent $event
*
*/
public function onCheck(FormEvent $event){
$user = $event->getForm()->getData();
$email = $user->getEmailCanonical();
$format = explode("#",$email);
if((strcmp($format[1] , "truc.com")===0) || (strcmp($format[1] , "chose.com") === 0)){
$url = $this->router->generate('list');
$response = new RedirectResponse($url);
$event->setResponse($response);
}else{
$event->getForm()->addError(new FormError("Enter a mail address with valid format"), 1);
var_dump($event->getForm()->getErrors());
die("Address is not valid");
}
}
}
My problem is once i add an error, i do not know how to display it on my form like for the errors already created by the bundle.
Thanks in advance.
I would not use the Event Dispatcher component for this, I'll just go simpler and create a custom validation constraint. Here is the link to the docs.
You can create a constraint that will check if, for example, your user has an specific domain in their email. Is the constraint doesn't pass, validation will fail, and thus, the registration process, giving you proper error information.
The docs explain it really well, but if you need help with the implementation let me know and I can update my answer.
UPDATE:
class RegistrationForm extends OtherForm
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->add('firstName', TextType::class, [
'required' => true,
'constraints' => [
new NotBlank(),
new Length(['min' => 2, 'max' => 20]),
]
])
->add('lastName', TextType::class, [
'required' => true,
'constraints' => [
new NotBlank(),
new Length(['min' => 2, 'max' => 20]),
]
])
->add('secondLastName', TextType::class, [
'required' => true,
'constraints' => [
new NotBlank(),
new Length(['min' => 2, 'max' => 20]),
]
])
->add('email', TextType::class, [
'required' => true,
'constraints' => [
new NotBlank(),
new CustomConstraint(),
new Length(['min' => 2, 'max' => 20]),
]
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
'csrf_protection' => false,
'allow_extra_fields' => true,
]);
}

Symfony dependent dropdown with 3 entities

So I'm about to create a form with three dropdowns which are interdependent.
When one or several channel1s are selected, the choices for channel 3 should change, according to what is selected for channel1. And dependent on that, the last dropdown "agencies" should change its choices.
I've already tried different solutions but none of them has worked so far. Right now I'm stuck on the solution provided by Symfony's documentation, which provides code for two entities but even with that one, my second dropdown doesn't have any values, so it's not working.
Here is my Form Type:
class SelectionType extends AbstractType {
protected $tokenStorage;
// private $manager;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
//solution Symfony Documentation
$channel1s = new Channel1();
$currentuser = $this->tokenStorage->getToken()->getUser();
$builder
->add('channel1s', EntityType::class, array(
'class' => 'AppBundle:Channel1',
'property' => 'name',
'label' => 'label.channel1s',
'empty_value' => 'label.select_channel1s',
'mapped' => false,
'expanded' => false,
'translation_domain' => 'UploadProfile',
'multiple' => true,
'required' => false,
));
$formModifier = function (FormInterface $form, Channel1 $channel1s = null) {
$channel3s = null === $channel1s ? array() : $channel1s->getChannel3();
$form->add('channel3s', EntityType::class, array(
'class' => 'AppBundle:Channel3',
'property' => 'name',
'label' => 'label.channel3s',
'empty_value' => 'label.select_channel3s',
'mapped' => false,
'expanded' => false,
'translation_domain' => 'UploadProfile',
'choices' => $channel3s,
'multiple' => true,
'choices_as_values' => true,
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
$data = $event->getData();
$formModifier($event->getForm(), $data->getChannel1s());
}
);
$builder->get('channel1s')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
$channel1s = $event->getForm()->getData();
$formModifier($event->getForm()->getparent(), $channel1s);
}
);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'DocumentBundle\Entity\UploadProfile'
));
}
public function getName()
{
return 'uploadprofile';
}
}
I've also tried a solution with Subscribers from that page: http://showmethecode.es/php/symfony/symfony2-4-dependent-forms/ but it didn't work out either..
I think my problem is somewhere around that line:
$channel3s = null === $channel1s ? array() : $channel1s->getChannel3();
but that's just a guess..
I also added that ajax function:
var $channel1s = $('#uploadprofile_channel1s');
$channel1s.change(function() {
var $form = $(this).closest('form');
var data = {};
data[$channel1s.attr('name')] = $channel1s.val();
// data[channel3s.attr('name')] = channel3s.val();
$.ajax({
url : $form.attr('action'),
type: $form.attr('method'),
data : data,
success: function(html) {
$('#uploadprofile_channel3s').replaceWith(
$(html).find('#uploadprofile_channel3s')
);
}
});
});
My 3 entities have ManytoMany or OneToMany relationships and I should have all the right getters and setters, but if anyone needs them to varify, let me know and I will upload them!
I've been stuck on this for quite a while now, so I would be happy about any kind of help or advise!
NOTE: there's still a third entity (agency) to be added but since not even the first one's are working, I decided to upload only the first two..
ADDED:
or maybe somebody can explain to my that line:
$channel3s = null === $channel1s ? array() : $channel1s->getChannel3s();
might be, that this is my problem?

Symfony Dynamic Generation for Submitted Forms with Form events

I'm in Symfony 3.2.4 and I have 3 entities : Country - Province - City. And I want do 3 fields populated dynamically.
I explain, I've 3 fields: Country > Province > City, the user choose a Country, the Province list is updated, he choose a Province, the City list is updated.
But I've a problem, for just one field dynamically updated, it's work, but no for 2 fields... Actually a user can choose a Country, and when he does it, the Province field is updated. But, when he choose a Province, the City field wasn't updated...
Here is my code :
# FormType
...
$builder->addEventSubscriber(new DynamicFieldsSubscriber());
...
# DynamicFieldsSubscriber
class DynamicFieldsSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
FormEvents::PRE_SET_DATA => 'preSetData',
FormEvents::PRE_SUBMIT => 'preSubmitData'
);
}
public function preSetData(FormEvent $event)
{
$location = $event->getData();
$form = $event->getForm();
$country = "";
$province = "";
$city = "";
if ($location) {
// collect preliminary values for 3 fields.
$country = $location->getEditeur();
$prov
ince = $location->getProvince();
$city = $location->getCity();
}
// Add country field as its static.
$form
->add('country', EntityType::class, array(
'class' => Editeur::class,
'choice_label' => 'country',
'label' => false,
'required' => true,
'placeholder' => 'Éditeur *',
'empty_data' => 'Éditeur *',
'attr' => array(
'class' => 'col-md-12 validate-required',
'placeholder' => 'Éditeur *'
)
))
;
// Now add all child fields.
$this->addProvinceField($form, $country);
$this->addCityField($form, $province);
}
/**
* Handling Form fields before form submits.
* #param FormEvent $event
*/
public function preSubmitData(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
// Here $data will be in array format.
// Add property field if parent entity data is available.
$country = isset($data['country']) ? $data['country'] : $data['country'];
$province = isset($data['province']) ? $data['province'] : null;
$city = isset($data['city']) ? $data['city'] : null;
// Call methods to add child fields.
$this->addProvinceField($form, $country);
$this->addCityField($form, $province);
}
/**
* Method to Add State Field. (first dynamic field.)
* #param FormInterface $form
* #param type $country
*/
private function addProvinceField(FormInterface $form, $country = null)
{
$countryCode = (is_object($country)) ? $country->getId() : $country;
// $countryCode is dynamic here, collected from the event based data flow.
$form
->add('province', EntityType::class, array(
'class' => Province::class,
'choice_label' => 'province',
'label' => false,
'required' => true,
'placeholder' => 'Province *',
'empty_data' => 'Province *',
'attr' => array(
'class' => 'col-md-12 validate-required',
'placeholder' => 'Province *'
),
'query_builder' => function (EntityRepository $er) use($countryCode) {
return $er->createQueryBuilder('p')
->where('p.country = :country')
->setParameter('country', $countryCode);
}
))
;
}
/**
* Method to Add District Field, (second dynamic field)
* #param FormInterface $form
* #param type $state
*/
private function addCityField(FormInterface $form, $province = null)
{
$provinceCode = (is_object($province)) ? $province->getId() : $province;
// $stateCode is dynamic in here collected from event based data flow.
$form->add('city', EntityType::class, array(
'class' => City::class,
'choice_label' => 'city',
'label' => false,
'required' => true,
'placeholder' => 'City *',
'empty_data' => 'City *',
'attr' => array(
'class' => 'col-md-12 validate-required',
'placeholder' => 'City *'
),
'query_builder' => function (EntityRepository $er) use($provinceCode) {
return $er->createQueryBuilder('e')
->where('e.province = :province')
->setParameter('province', $provinceCode);
}
));
}
}
## jQuery
var $country = $('#ec_country');
$country('change', function() {
var $form = $(this).closest('form');
var data = {};
data[$country('name')] = $country();
$.ajax({
url : $form.attr('action'),
type: $form.attr('method'),
data : data,
success: function(html) {
$('#ec_province').replaceWith(
$(html).find('#ec_province')
);
}
});
});
var $province = $('#ec_province');
$(document).on('change', $province, function() {
var $form = $(this).closest('form');
var data = {};
data[$programme.attr('name')] = $('#ec_province').val();
$.ajax({
url : $form.attr('action'),
type: $form.attr('method'),
data : data,
success: function(html) {
$('#ec_city').replaceWith(
$(html).find('#ec_city')
);
}
});
});
Any idea?

multiple choice dropdown with option groups using symfony “entity”?

I have the entity Property with manyToMany to Feature that is oneToMany of FeatureType. The multi-choice drop-down is being implemented in the Property create form.
PropertyRoomAdmin.php
protected function configureFormFields(FormMapper $formMapper)
{
$property = $this->getProperty();
$featuresChoices = $this->getRepository('TestBundle:Feature')->getChoicesWithCategoryGroup();
$formMapper
->add('features', 'entity', array(
'label' => '設備(こだわり条件?)',
'class' => 'TestBundle:Feature',
'choices' => $featuresChoices,
'property' => 'name'
))
;
}
FeatureRepository.php
public function getChoicesWithCategoryGroup()
{
$choices = array();
$qb = $this->createQueryBuilder('p');
$qb->select('p, c');
$qb->LeftJoin('p.featureCategory', 'c');
$qb->orderBy('c.name', 'DESC')->addOrderBy('p.name', 'DESC');
$products = $qb->getQuery()->execute();
$choices = [];
foreach ($products as $product) {
$choices[$product->getFeatureCategory()->getName()][] = $product;
}
return $choices;
}
Neither the property "features" nor one of the methods "addFeatur()"/"removeFeatur()", "addFeature()"/"removeFeature()",
"setFeatures()", "features()", "__set()" or "__call()" exist and have
public access in class "TestBundle\Entity\PropertyRoom".
I tried 'multiple' => true code got error
->add('features', 'entity', array(
'label' => '設備(こだわり条件?)',
'class' => 'EstateBundle:Feature',
'choices' => $featuresChoices,
'property' => 'name',
'multiple'=> true,
'required' => false
))
ERROR - Failed to create object: EstateBundle\Entity\PropertyRoom
Context: {"exception":"Object(Sonata\AdminBundle\Exception\ModelManagerException)","previous_exception_message":"An exception occurred while executing 'INSERT INTO property_room_features (property_room_id, feature_id) VALUES (?, ?)' with params [168, 50]:\n\nSQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '168-50' for key 'PRIMARY'"}
Where you setup your options array:
foreach ($products as $product) {
$choices[$product->getFeatureCategory()->getName()][] = $product;
}
Change it to something like this:
foreach ($products as $product) {
$choices[$product->getFeatureCategory()->getName()][$product->getName()] = $product->getId();
}

How to disable specific item in form choice type?

I have a form with choice field of entities from database:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('categories', 'document', array(
'class' => 'Acme\DemoBundle\Document\Category',
'property' => 'name',
'multiple' => true,
'expanded' => true,
'empty_value' => false
));
}
This form will produce the list of checkboxes and will be rendered as:
[ ] Category 1
[ ] Category 2
[ ] Category 3
I want to disable some of the items by value in this list but I don't know where I should intercept choice field items to do that.
Does anybody know an solution?
you can use the 'choice_attr' in $form->add() and pass a function that will decide wether to add a disabled attribute or not depending on the value, key or index of the choice.
...
'choice_attr' => function($key, $val, $index) {
$disabled = false;
// set disabled to true based on the value, key or index of the choice...
return $disabled ? ['disabled' => 'disabled'] : [];
},
...
Just handled it with finishView and PRE_BIND event listener.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('categories', 'document', array(
'class' => 'Acme\DemoBundle\Document\Category',
'property' => 'name',
'multiple' => true,
'expanded' => true,
'empty_value' => false
));
$builder->addEventListener(FormEvents::PRE_BIND, function (FormEvent $event) {
if (!$ids = $this->getNonEmptyCategoryIds()) {
return;
}
$data = $event->getData();
if (!isset($data['categories'])) {
$data['categories'] = $ids;
} else {
$data['categories'] = array_unique(array_merge($data['categories'], $ids));
}
$event->setData($data);
});
}
...
public function finishView(FormView $view, FormInterface $form, array $options)
{
if (!$ids = $this->getNonEmptyCategoryIds()) {
return;
}
foreach ($view->children['categories']->children as $category) {
if (in_array($category->vars['value'], $ids, true)) {
$category->vars['attr']['disabled'] = 'disabled';
$category->vars['checked'] = true;
}
}
}

Resources