I can't retrieve data from my form, I tried differents ways but no result. My repository :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('min_price', 'text', array('mapped' => false, 'label' => 'De la :', 'attr'=>
array(
'placeholder'=>'Pretul minim',
'class'=>'form-control')))
->add('max_price', 'text', array('mapped' => false, 'label' => 'Pina la :' , 'attr'=>
array(
'placeholder'=>'Pretul maxim',
'class'=>'form-control')))
)
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
parent::setDefaultOptions($resolver);
$resolver->setDefaults(array(
// avoid to pass the csrf token in the url (but it's not protected anymore)
'csrf_protection' => false,
));
}
public function getName()
{
return '';
}
My controller :
public function showCategoryAction($id, $page, Request $request){
$em = $this->getDoctrine()->getManager();
$repositoryProduct = $em->getRepository('ShopDesktopBundle:Product');
$category = $em->getRepository('ShopDesktopBundle:Category')->findOneById($id);
if (!$category) {
throw $this->createNotFoundException('Category not found.');
}
$aFilter = array();
$entity = new Product();
$form = $this->createForm(new ProductType(), $entity,array(
'action' => $this->generateUrl('show_product_category',array("id" => $id, "name" => $category->getCategoryLink(), "page" => $page )), //Your url to generate
'method' => 'GET'
));
$form->handleRequest($request);
$aFilter['iMinPrice'] = $form["min_price"]->getData();
$aFilter['iMaxPrice'] = $form["max_price"]->getData();
print_r($aFilter);
//Searchs products
$aProducts = $repositoryProduct->getProductsOrderByDateDesc($id,null,$aFilter);
if (!$aProducts) {
throw $this->createNotFoundException('Products not found.');
}
//Create pagination
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$aProducts,
$page,
3
);
//Send data to view
return $this->render('ShopDesktopBundle:Category:category.html.twig',array(
'category' => $category,
'pagination' => $pagination,
'form' => $form->createView()
));
}
My view :
<form action="{{ path('show_product_category',{ 'id':category.getId(), 'name':category.getCategoryLink() }) }}" method="get" {{ form_enctype(form) }}>
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="" href="#toggleOne">
<em class="icon-minus icon-fixed-width"></em>Pret
</a>
</div>
<div id="toggleOne" class="accordion-body collapse in">
<div class="accordion-inner">
{{ form_widget(form) }}
</div>
</div>
</div>
<input type="submit" class="btn btn-primary marg-left-20" value="Cautare"/>
</form>
The view :
show_product_category:
path: /{id}/{name}/{page}
defaults: { _controller: ShopDesktopBundle:Category:showCategory, page: 1}
requirements:
id: \d+
page: \d+
_method: GET|POST
So the problem is that I can't retrieve data from thi form. For all situations $aFilter is empty. If for example I put in the view in form POST method the filter is with data from form. My url look like this :
?min_price=10&max_price=50.
Help me please. Thx in advance.Exist a solution??
I would not set the form method as GET, just do not specify a method and it will default to POST, which is the usual way to submit a form.
Then handle the form submission in your Controller when the method is POST - like this:
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isValid() {
$aFilter['iMinPrice'] = $form->get('min_price')->getData();
$aFilter['iMaxPrice'] = $form->get('max_price')->getData();
}
}
More information on how to handle form submissions in Symfony2 here.
If you really need the form method to be GET, you should be able to get the query string parameters from the request:
$aFilter['iMinPrice'] = $request->query->get('min_price');
$aFilter['iMaxPrice'] = $request->query->get('max_price');
Related
I followed this tutorial to add a captcha to my form.
First I install it using
composer require captcha-com/symfony-captcha-bundle:"4.*"
After I Install it, I got an error on a file called captcha.html.twig
Error:
captcha Unexpected "spaceless" tag (expecting closing tag for the
"block" tag defined near line 2).
So I changed {% spaceless %} to {% apply spaceless %}
And the error is gone.
But My captcha bot always returns True (even when I don't even fill it.
Here is the ->add() function of my form:
->add('captchaCode', CaptchaType::class, [
'captchaConfig' => 'ExampleCaptchaUserRegistration',
'constraints' => [
new ValidCaptcha([
'message' => 'Invalid captcha, please try again',
]),
],]);
Code of Routes.yaml :
captcha_routing:
resource: "#CaptchaBundle/Resources/config/routing.yml"
Code of captcha.php :
<?php
// app/config/packages/captcha.php
if (!class_exists('CaptchaConfiguration')) { return; }
// BotDetect PHP Captcha configuration options
return [
// Captcha configuration for example form
'ExampleCaptchaUserRegistration' => [
'UserInputID' => 'captchaCode',
'ImageWidth' => 250,
'ImageHeight' => 50,
],
];
Captcha field on the User.php entity:
protected $captchaCode;
public function getCaptchaCode()
{
return $this->captchaCode;
}
public function setCaptchaCode($captchaCode)
{
$this->captchaCode = $captchaCode;
}
Code in the View (twig)
<span class="txt1 p-b-11">
Are You a Robot?
</span>
<div class="wrap-input100 m-b-36">
{{ form_widget(form.captchaCode, {'attr': {'class': 'input100'} }) }}
<span class="focus-input100"></span>
</div>
<div class="error">{{ form_errors(form.captchaCode) }} </div>
Controlleur function:
/**
* #Route("/register", name="user_register", methods={"GET","POST"})
*/
public function register(Request $request,UserPasswordEncoderInterface $encoder): Response
{
$user = new User();
$form = $this->createForm(UserType::class, $user, ['validation_groups' => ['register'], ]);
$form ->remove("description");
$form ->remove("phone");
$form ->remove("website");
$form ->remove("facebook");
$form ->remove("picture");
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$hash = $encoder->encodePassword($user,$user->getPassword());
$user->setPassword($hash);
// defaults values (user can edit them later)
$user->setDescription("Apparently, this User prefers to keep an air of mystery about them.");
$user->setPhone(null);
$user->setPicture("default.png");
$user->setWebsite(null);
$user->setFacebook(null);
$user->setRoles(["ROLE_USER"]);
// end default values
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
return $this->redirectToRoute('user_login');
}
return $this->render('authentication/register.html.twig', [
'user' => $user,
'form' => $form->createView(),
]);
}
I am working with Symfony2 and I am trying to create new entity Collection without page reload. My controller works fine, but I have issues with Ajax, I am NOT well familiar with it. Below is the code I already have. When I press submit button, new entity is saved in db, but entity doesn't appear on page.
CollectionController
/**
* #Route("/create-collection", name="collection_create_collection")
* #Template()
*/
public function createAction(Request $request)
{
$collection = new Collection();
$form = $this->createForm(
new CollectionType(),
$collection,
array('method' => 'POST',
'action' => $this->generateUrl('collection_create_submit'),
)
);
return array('collection'=>$collection, 'form' => $form->createView());
}
/**
* #Route("/collection_create_submit", name="collection_create_submit")
*/
public function createSubmitAction(Request $request)
{
$collection = new Collection();
$user = $this->getUser();
$form = $this->createForm(
new CollectionType(),
$collection,
array('method' => 'POST',
)
);
$form->handleRequest($request);
if ($form->isValid() && $form->isSubmitted()) {
$colname = $form["name"]->getData();
$existing = $this->getDoctrine()->getRepository('CollectionBundle:Collection')->findBy(['name' => $colname, 'user' => $user]);
if ($existing) {
return new JsonResponse(['error' => 'Collection with such name already exists']);
}
$em = $this->getDoctrine()->getManager();
$em->persist($collection);
$em->flush();
return new JsonResponse(array(
'success' => $collection
));
}
}
create.html.twig
{% include 'CollectionBundle:Collection:collectionJS.html.twig' %}
<div class="collection-create">
<h3 id="create-collection">Create a collection</h3>
<a class="close-reveal-modal" aria-label="Close">×</a>
{{ form_start(form, {'attr' : {'action' : 'collection_create_collection', 'id': 'create-collection-form'}}) }}
{{ form_widget(form) }}
<a class="button custom-close-reveal-modal" aria-label="Close">Cancel</a>
<button type="submit" value="create" class="right" onclick="createCollection();">Create</button>
{{ form_end(form) }}
</div>
<script type="application/javascript">
$('a.custom-close-reveal-modal').on('click', function(){
$('#externalModal').foundation('reveal', 'close');
});
</script>
collectionJS.html.twig
function createCollection(){
var $form = $('#create-collection-form');
$($form).submit(function(e) {
e.preventDefault();
$.ajax({
type: "POST",
url: $form.attr('action'),
data: $form.serialize()
}).done(function( data ) {
if(data.error)
{
console.log(data.error);
} else if(data.success) {
var collection = data.success;
$('.griditems').prepend('<p>' + collection + '</p>');
$('#externalModal').foundation('reveal', 'close');
}
});
});
}
UPD
The submit is triggered, but now I get undefined instead of entity. Probably, I am sending wrong json response.
UPD
I tried to encode collection entity.
In createSubmitAction I changed return to
$jsonCollection = new JsonEncoder();
$jsonCollection->encode($collection, $format = 'json');
return new JsonResponse(array(
'success' => $jsonCollection
));
How do I get this response in Ajax?
JsonResponse cannot transform your entities into JSON. You need to use a serializer library like JMSSerializerBundle or implement a serializing-method inside your entity.
Check the answers provided here.
How to encode Doctrine entities to JSON in Symfony 2.0 AJAX application?
You have to return a simple $collection object as the standard doctrine entity objects are too large in size. What I recommend is:
return new JsonResponse(array(
'success' => $collection->toArray()
));
and adding a new method to your entity class:
public function toArray(){
return array(
'id' =>$this->getId(),
'name'=>$this->getName(),
// ... and whatever more properties you need
); }
I have on my form template new.html.twig a select where all the elements of an entity are loaded ($categories).
Controller
public function newAction(Request $request){
$entity = new Playlist();
$form = $this->createCreateForm($entity);
$em = $this->getDoctrine()->getManager();
$categories = $em->getRepository('PublicartelAppBundle:Category')->getAllCategories();**
return $this->render('PublicartelAppBundle:Playlist:new.html.twig', array(
'categories' => $categories,
'entity' => $entity,
'form' => $form->createView(),
));
}
Select filter that serves to make a search.
Select in my twig template that displays all categories obtained from the query.
new.html.twig
<div class="form-group">
<label for="publicartel_appbundle_category_name">Search for category: </label>
<select id='selectCategory' class="form-control select2">
{% for category in categories %}
<option>
{{ category.name }}
</option>
{% endfor %}
</select>
</div>
JS in my twig template that detects changes in select option to make a new query and retrieve records from the selected option.
JS code
$('#selectCategory').on('change', function () {
var optionSelect = $(this).val();
$.post("{{path('playlist_category') }}", {category: optionSelect},
function (filterContent) {
for (var content in filterContent.category_result) {
for (var name in filterContent.category_result[content]) {
var result = filterContent.category_result[content][name];
console.log(result);
$('#playlist_content_name').append('<option>' + result + '</option>');
}
}
}, 'json');
});
The result of the new query is done in the playlist_category route is assigned to another select this in my twig template with the append method.
<div class="form-group">
<label for="publicartel_appbundle_area_name">Content</label>
{{ form_widget(form.items.vars.prototype.content, { 'id': 'playlist_content_name', 'full_name': '', required: false, 'attr': {'class': 'form-control select2'}}) }}
</div>
This select load other options, but the other select is used to filter options to prevent all options be loaded.
My problem is that when I try to send the form with any of the options obtained from the search, I get an error that the variable categories does not exist in my template twig new.html.twig.
Then, as the method createAction, also conducts a rendering of the template new.html.twig also add the variable $ categories there.
Controller
public function createAction(Request $request){
$entity = new Playlist();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
$em = $this->getDoctrine()->getManager();
if ($form->isValid()) {
// $em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('playlist_show', array(
'id' => $entity->getId())));
}
$categories = $em->getRepository('PublicartelAppBundle:Category')->getAllCategories();
return $this->render('PublicartelAppBundle:Playlist:new.html.twig', array(
'categories' => $categories,
'entity' => $entity,
'form' => $form->createView(),
));
}
But when complete the form, having chosen an option of select which return the search, instead of addressing the playlist_show route, directs me to the path /create with the form new.html.twig.
I'm trying to create a search form with multiple criteria but it doesn't work, and I think the controller does not receive the form because when I click Button Submit the page reloads only.
This is the Controller
/**
* #ParamConverter("agence", options={"mapping": {"agence_slug":"slug"}})
*/
public function indexAction(Agence $agence, Request $request)
{
$form = $this->createForm(new SearchTravelType());
$request = $this->getRequest();
$em = $this->getDoctrine()->getManager();
if ($request->getMethod() == 'POST')
{
$form->bind($request);
if ($form->isValid())
{
$criteria = $form->getData();
$listTravels = $em->getRepository('ProjectTravelBundle:Travel')->getListBy($criteria, $agence);
}
}
$listTravels = $em->getRepository('ProjectTravelBundle:Travel')->findByAgence($agence);
return $this->render('ProjectDashboardBundle:Travel:index.html.twig',
array(
'listTravels' => $listTravels,
'agence' => $agence,
'form' => $form->createView() ,
));
}
and this is the queryBuilder
class TravelRepository extends EntityRepository
{
public function getListBy($criteria, $agence)
{
$qb = $this->createQueryBuilder('t');
$qb = $this->whereAgence($qb, $agence);
$qb ->leftJoin('t.airport', 'a')
->addSelect('a');
foreach ($criteria as $field => $value) {
if (!$this->getClassMetadata()->hasField($field)) {
// Make sure we only use existing fields (avoid any injection)
continue;
}
$qb ->andWhere($qb->expr()->eq('t.'.$field, ':t_'.$field))
->setParameter('t_'.$field, $value);
}
return $qb->getQuery()->getResult();
}
public function whereAgence (\Doctrine\ORM\QueryBuilder $qb, $agence)
{
$qb->where('a.agence = :agence')
->setParameter('agence', $agence);
return $qb;
}
}
and this is the page twig and the form
<form class="form-horizontal" role="form" method="post" >
<td>{{ form_widget(form.id) }}</td>
<td class="center">-</td>
<td>{{ form_widget(form.title) }}</td>
<td>{{ form_widget(form.country) }}</td>
<td>{{ form_widget(form.destination) }}</td>
<td>{{ form_widget(form.airport) }}</td>
<td>{{ form_widget(form.departureDate) }}</td>
<td>{{ form_widget(form.returnDate) }}</td>
<td>{{ form_widget(form.price) }}</td>
<td>{{ form_widget(form.enabled) }}</td>
<td><span class="input-group-btn">
<button type="submit" class="btn btn-purple btn-sm">Search
<i class="icon-search icon-on-right bigger-110"></i></button>
</span>
</form>
I think the first problem is that form is not recovered in the controller, I tried with
$listTravels = $em->getRepository('ProjectTravelBundle:Travel')->find(1);
instead
getListBy($criteria, $agence)
to see what gives. the controller ignores the form and it goes directly to the following queries
$listTravels = $em->getRepository('ProjectTravelBundle:Travel')->findByAgence($agence);
You can remove $request = $this->getRequest(); from action as you are passing REquest object to this action;
You need to add action to your form,
like this:
$this->createForm(new SearchTravelType(), null, [
'action' => $this->generateUrl('ROUT')
]);
or like this:
<form class="form-horizontal" role="form" method="post" action="{{ path('ROUT') }}" >
EDIT:
We create a filter form with GET method (you should use POST method for inserting to DB, not for fetching results), disable CSRF protection. We create a controller action:
public function indexAction(Agence $agence, Request $request)
{
$form = $this->createForm(new SearchTravelType(), null, [
'action' => $this->generateUrl('ROUTE'),
'method' => 'GET'
]);
$form->handleRequest($request);
if ($form->isValid())
{
$em = $this->getDoctrine()->getManager();
$criteria = explode('&', $request->query->get($form->getName())); // I didn't test this line, you should check it..
$listTravels = $em->getRepository('ProjectTravelBundle:Travel')->getListBy($criteria, $agence);
// Terminate the request
return $this->render('ProjectDashboardBundle:Travel:index.html.twig',
array(
'listTravels' => $listTravels,
'agence' => $agence,
'form' => $form->createView() ,
));
}
$listTravels = $em->getRepository('ProjectTravelBundle:Travel')->findByAgence($agence);
return $this->render('ProjectDashboardBundle:Travel:index.html.twig',
array(
'listTravels' => $listTravels,
'agence' => $agence,
'form' => $form->createView() ,
));
}
You can try this bundle:
https://github.com/petkopara/PetkoparaMultiSearchBundle
Provides form or service for multi criteria search in Doctrine Entity.
In your case the form solution will solve your issue:
First in your form type just only add the MultiSearchType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('search', MultiSearchType::class, array(
'class' => 'ProjectTravelBundle:Travel'));
}
Then in your Controller add the following code
public function indexAction(Request $request)
{
$search = $request->get('search');
$em = $this->getDoctrine()->getManager();
$queryBuilder = $em->getRepository('ProjectTravel:Travel')->createQueryBuilder('e');
$filterForm = $this->createForm('ProjectTravelBundle\Form\TravelType');
// Bind values from the request
$filterForm->handleRequest($request);
if ($filterForm->isValid()) {
// Build the query from the given form object
$queryBuilder = $this->get('petkopara_multi_search.builder')->searchForm($queryBuilder, $filterForm->get('search'));
}
..
}
At the last render your Travel form in your template
{{form_render(filter_form)}}
I want send data via PUT method, my controller action:
public function updateTestAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$progress = $em->getRepository('CodeCatsPanelBundle:Progress')->find(5);
//$form = $this->createForm(new ProgressType(), $progress, array('method' => 'PUT'))->add('submit', 'submit');
$form = $this->createForm(new ProgressType(), $progress)->add('submit', 'submit');
$form->handleRequest($request);
return $this->render('CodeCatsPanelBundle:Progress:test.html.twig', [
'form' => $form->createView(),
'valid' => $form->isValid(),
'progress' => $progress,
'request' => $request
]);
}
the first one form works correct, but when I change method to PUT I receive validation error:
This form should not contain extra fields.
I know that Symfony2 use post and extra hidden field _method but how to valid data in this case?
just add a hidden input in your template like:
<form action='your route'>
<input type='hidden' name='_method' value='PUT'>
//do something.......
</form>
in your action:
public function updateTestAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$progress = $em->getRepository('CodeCatsPanelBundle:Progress')->find(5);
$form = $this->createForm(new ProgressType(), $progress)->add('submit', 'submit');
$form->handleRequest($request);
if ($form->isValid()){
//do something
}
return $this->render('CodeCatsPanelBundle:Progress:test.html.twig', [
'form' => $form->createView(),
'valid' => $form->isValid(),//you need this?
'progress' => $progress,
'request' => $request
]);
}
in your route config file:
yourRouteName:
path: /path
defaults: { _controller: yourBundle:XX:updateTest }
requirements:
_method: [PUT]
Most browsers do not support sending PUT and DELETE requests via the
method attribute in an HTML form.
Fortunately, Symfony provides you with a simple way of working around
this limitation.
Symfony 3
Enable http-method-override
In web/app.php:
Request::enableHttpMethodParameterOverride(); // add this line
Choose one of the following override:
In a Twig Template
{# app/Resources/views/default/new.html.twig #}
{{ form_start(form, {'action': path('target_route'), 'method': 'GET'}) }}
In a Form
form = $this->createForm(new TaskType(), $task, array(
'action' => $this->generateUrl('target_route'),
'method' => 'GET',
));
In a Controller / the lazy way
$form = $this->createFormBuilder($task)
->setAction($this->generateUrl('target_route'))
->setMethod('GET')
->add('task', 'text')
->add('dueDate', 'date')
->add('save', 'submit')
->getForm();
Post-Symfony 2.2
Same as above, just Step 2, Step 1 is done by default.
Pre-Symfony 2.2
Same as above, Step 1 and 2.
References
Faking the method with _method
Changing the action and methods in a form
Symfony configuration with http-method-override