Form doesn't get submitted - php

I have started to study Symfony2 since I will probably need in my work.
routing.yml:
account_register:
path: /register
defaults: {_controller: AppBundle:Register:index}
RegisterController:
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Entity\User;
class RegisterController extends Controller
{
/**
* #Route("/register")
*/
public function indexAction(Request $request)
{
$register = new User();
$form = $this->createFormBuilder($register)
->add('email', 'email', array('required' => false))
->add('password', 'password', array('required' => false))
->add('alias', 'text', array('required' => false))
->add('register', 'submit', array('label' => 'Register'))
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
// perform some action, such as saving the task to the database
$em = $this->getDoctrine()->getManager();
$em->persist($register);
$em->flush();
exit("Error");
//return $this->redirectToRoute('task_success');
}
return $this->render('pages/register.html.twig', array(
'form' => $form->createView(),
));
}
}
regiser.html.twig:
{% extends 'base.html.twig' %}
{% block body %}
<br /><br />
<div class = "window">
<form>
<br /><br /><br /><br /><br /><br /><br />
{{ form_start(form) }}
{{ form_errors(form) }}
<div id=center-text>Email</div>
<div class="textfield" id=center> {{ form_widget(form.email, {'attr': {'class': 'textfield', 'size': '22', 'maxlength': '100'}}) }} </div>
<br />
<div id=center-text>Password</div>
<div class="textfield" id=center> {{ form_widget(form.password, {'attr': {'class': 'textfield', 'size': '22', 'maxlength': '100'}}) }} </div>
<br />
<div id=center-text>Alias</div>
<div class="textfield" id=center> {{ form_widget(form.alias, {'attr': {'class': 'textfield', 'size': '22', 'maxlength': '100'}}) }}</div>
<br /><br />
<br />
<center>
{{ form_widget(form.register, {'attr': {'class': 'button'}}) }}
</center>
{{ form_end(form) }}
</form>
{% endblock %}
When i press the submit button only the url changes from http://localhost/website/web/app_dev.php/register
to
http://localhost/website/web/app_dev.php/register?form%5Bemail%5D=&form%5Bpassword%5D=&form%5Balias%5D=&form%5Bregister%5D=&form%5B_token%5D=hd70y_KjUEY8v51dQjnjU0ZMTJ0BYOihurV6IcIvghY

What is happening is the expected form's flow. The form that you are submitting is redirecting to the same page.
If you don't want your form to be in GET, you can change it for POST :
$form = $this->createFormBuilder($register)
->setMethod('POST')
->...
When you are redirected after submitting the form, $form->handleRequest($request) binds the request (your data submitted) with the form that is just created. $form->isValid() then checks if your data is valid according to your form.
If you don't see any change after being redirected, you should check if $form->isValid() returns true.
If you want to redirect your form to another controller method, you should create another resource and then set the action attribute of your form thanks to the setAction() method.
To sum up, everything that I just told you is written and explained on this page, and you definitely should read it ! :-).

Silly me, the html was my test code and then i added the symfony {{ blocks }} and forgot to remove the old tags

Related

Symfony CSRF invalid token: Mismatch between token in URL and token in form

I want to implement a form in Symfony that filters a data set for me.
The extract of my twig file as well as the the FilterType that is used for the form are shown below.
list.html.twig
{% block filterContent %}
{{ form_start(form) }}
<div class="row">
{#This renders a red banner if the form contains errors.#}
{#If the form variable is not called "form", pass it explicitly.#}
{% include 'Form/form_errors_banner.html.twig' with {'form': form} %}
{{ form_row(form.component) }}
{{ form_row(form._token) }}
{{ form_errors(form) }}
</div>
<input type="reset" id="resetter" class="btn-primary btn btn-xs" value="{{ 'label.resetAll'|trans }}"/>
<input type="submit" class="btn-primary btn btn-xs" value="{{ 'label.applyFilter'|trans }}"/>
{{ form_end(form) }}
<!-- <br clear="all" /> -->
{% endblock filterContent %}
FilterType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->setAction($options['data']['url'])
->setMethod('GET')
->add('component', ChoiceType::class, array(
'label' => 'Component',
'placeholder' => 'Select Component',
'choices' => array(
'All' => 'All',
'Document' => 'Document',
'User' => 'User',
'Waiver' => 'Waiver'
),
'required' => false,
));
}
For some reason I get the following error message indicating that my CSRF token is invalid.
CSRF invalid error message
After having a closer look into this, I suspect that the error is caused, because the CSRF token in the transmitted URL differs from the one that is sent with the form:
CSRF token mismatch
I already tried to remove {{ form_row(form._token) }} line in my twig file and cleared my browser and server cache, but still the error message pops up.
Could anyone help me and tell me what I did wrong?
In FilterType.php, ensure that you are using the same ID for your token as in your twig form. You can customize it via configureOptions:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'csrf_token_id' => FilterType::class
]);
}

Symfony : form with GET method, messy URL

I use a search form in Symfony 4.2.5, with GET method.
But the URL is not very... sexy.
I want to get a clean URL.
I have already disabled CSRF protection, and removed the submit from the FormBuilder ( otherwise, the submit button was ALSO on the URL).
The form :
public function searchForm()
{
//Form search creation
$form = $this->createFormBuilder(null, array('csrf_protection' => false))
->setAction($this->generateUrl('page'))
->setMethod('GET')
->add('object', TextType::class)
->getForm();
return $this->render('page.html.twig', ['searchForm' => $searchForm->createView()]);
}
The view :
<form class="search">
{{ form_start(searchForm) }}
{{ form_row(searchForm.object, {'attr' : {'placeholder': "Search..."}}) }}
<button id="searchSubmit" class="btn btn-success">Search </button>
{{ form_end(searchForm) }}
</form>
With this code, I get localhost/page?form[object]=SearchTerm
I know, it is a detail, but I want to get an URL like localhost/page?object=SearchTerm.

Using same view for editing and viewing symfony

I'd like to use the same view for both editing and viewing. Unfortunatly, I cannot edit my view. In symfony3, I think there is no way to index a form. I tried every thing I could but I don't know how I can use the same form. In my project, I use also JEE (linked directly to data base) to communicate with symfony using UniRest API. Here are my view and edit controllers:
/**
* #Method({"GET"})
*/
public function viewAction($id) {
$phone = new Phone();
$form = $this->createForm(PhoneType::class, $phone);
$headers = array('Accept' => 'application/json');
$response = Unirest\Request::get(link/phones/'.$id,$headers);
//$this->assertEquals(Response::HTTP_OK, $response->getStatusCode());
return $this->render('AppBundle:Phone:PhoneView.html.twig', array (
'form' => $form->createView(),
'phone' => $response->body,
) );
}
/**
* #Method({"PUT"})
*/
public function updateAction(Request $request, $id) {
$phone = new Phone();
$form = $this->createForm(PhoneType::class, $phone);
dump($request->getMethod());
if ($request->isMethod('PUT')) {
$form->handleRequest($request);
$headers = array('Content-Type' => 'application/json');
$data = json_encode($phone);
$response = Unirest\Request::put('link/phones/'.$id,$headers,$data);
//$this->assertEquals(Response::HTTP_OK, $response->getStatusCode());
dump($response->code);
return $this->redirect($this->generateUrl('phones_list'));
}
$headers = array('Accept' => 'application/json');
$response = Unirest\Request::get('link/phones/'.$id,$headers);
//$this->assertEquals(Response::HTTP_OK, $response->getStatusCode());
dump($response->code);
dump($response->body);
return $this->render('AppBundle:Phone:PhoneUpdate.html.twig', array(
'form'=> $form->createView(),
'phone'=> $response->body,
));
And here is my file PhoneView.html.twig
{% extends "::base.html.twig" %}
{% block title %}Accedant - {{ parent() }}{% endblock %}
{% block body %}
<form novalidate="novalidate" method = "get">
<p>
<label> color </label> :<input type="text" value= {{ phone.color }} />
<label> price </label> :<input type="text" value= {{ phone.price }} />
<div class="form-group col-md-offset-5">
<button type="submit" class="btn btn-default">Save</button>
</div>
</p>
</form>
{# Updating Phone #}
<p class="left-center">
<a href="{{ path('phones_update', {'id': phone.id}) }}" class="btn btn-mini btn-danger" class="btn btn-mini btn-danger">
Modify phone
</a>
</p>
{% endblock %}
And here is my PhoneUpdate.html.twig
{% extends "::base.html.twig" %}
{% block title %} Phone - {{ parent() }}{% endblock %}
{% block body %}
<div class="container">
{{ form_start(form, {'method': 'PUT'}) }}
<input type="hidden" name'_METHOD' value="PUT">
{{ form_widget(form) }}
<input type="submit" value="Sauvegarder" class="btn btn-default" />
{{ form_end(form) }}
</div>
{% endblock %}
and here is my file routing.yml
phones_view:
path: /phones/{id}
defaults: { _controller: AppBundle:Phone:view }
methods: [GET]
requirements:
id: \d+
phones_update:
path: /phones/{id}
methods: [PUT]
defaults: { _controller: AppBundle:Phone:update }
requirements:
id: \d+
Thank you for your help.
First of all, my put and delete method was not configurated. Moreover, my problem was that I thought that the put method in my routing file routing.yml has no relation with my web services. So I change my path in order to edit my form /update/{id}, and after that I got a 404 error that was because of my implementation in J2EE side.

Symfony 2 form not pre-populating with pre-saved data

Im taking over a project in Symfony 2 (of which I have little knowledge) and am having problems with one of the existing forms. It should be pre-populating the form fields with existing data but is failing to do so. Can anybody give and suggestions as to why it may not be working?
Heres my code:
/**
* #Route("/admin/pressrelease/{id}")
* #Template("ImagineCorporateBundle:Admin:Pressrelease/edit.html.twig")
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getEntityManager();
$repo = $em->getRepository('ImagineCorporateBundle:PressRelease');
$pr = $repo->find($id);
if(!$pr->getDocument())
{
$doc = new Document();
$doc->setType('child');
$doc->setTemplate('child');
$pr->setDocument($doc);
}
$dateHelper = $this->get('helper.datehelper');
$years = $dateHelper->dateRangeAction();
$form = $this->createForm(new PressreleaseType(), array($pr , $years) );
if($this->getRequest()->getMethod() == 'POST')
{
$form->bindRequest($this->getRequest());
if($pr->getDocument())
{
$pr->getDocument()->setType('child');
$pr->getDocument()->setTemplate('child');
$pr->getDocument()->setTitle($pr->getTitle());
}
if($form->isValid())
{
$pr->upload('../web/upload/general/');
$em->persist($pr);
$em->persist($pr->getDocument());
$em->flush();
$pr->index(
$this->get('search.lucene'),
$this->generateUrl(
'imagine_corporate_pressrelease_view',
array('id' => $pr->getId(), 'title' => $pr->getTitle())
)
);
return $this->redirect($this->generateUrl('imagine_corporate_pressrelease_admin'));
}
}
return array('pressrelease' => $pr, 'form' => $form->createView());
}
And the view template:
{% extends "ImagineCorporateBundle:Admin:base.html.twig" %}
{% block heading %}Edit Press Release{% endblock %}
{% block content %}
<p>
Upload Attachment |
New Person
</p>
<form action="" method="post" {{ form_enctype(form) }}>
<div>
{{ form_label(form.title) }}
{{ form_errors(form.title) }}
{{ form_widget(form.title) }}
</div>
<div>
{{ form_label(form.author) }}
{{ form_errors(form.author) }}
{{ form_widget(form.author) }}
</div>
<div>
{{ form_label(form.postdate) }}
{{ form_errors(form.postdate) }}
{{ form_widget(form.postdate) }}
</div>
<div>
{{ form_label(form.imageUpload) }}
{{ form_errors(form.imageUpload) }}
{{ form_widget(form.imageUpload) }}
</div>
<div>
{{ form_label(form.thumbnailUpload) }}
{{ form_errors(form.thumbnailUpload) }}
{{ form_widget(form.thumbnailUpload) }}
</div>
<fieldset>
<div><input type="checkbox" class="checkallWebsites"> Check all</div>
{{ form_label(form.websites) }}
{{ form_errors(form.websites) }}
{{ form_widget(form.websites) }}
</fieldset>
<fieldset>
<div><input type="checkbox" class="checkallMagazines"> Check all</div>
{{ form_label(form.magazines) }}
{{ form_errors(form.magazines) }}
{{ form_widget(form.magazines) }}
</fieldset>
<fieldset>
<div><input type="checkbox" class="checkallDept"> Check all</div>
{{ form_label(form.department) }}
{{ form_errors(form.department) }}
{{ form_widget(form.department) }}
</fieldset>
<script>
$(function () {
$('.checkallWebsites').click(function () {
$(this).parents('fieldset:eq(0)').find(':checkbox').attr('checked', this.checked);
});
});
$(function () {
$('.checkallMagazines').click(function () {
$(this).parents('fieldset:eq(0)').find(':checkbox').attr('checked', this.checked);
});
});
$(function () {
$('.checkallDept').click(function () {
$(this).parents('fieldset:eq(0)').find(':checkbox').attr('checked', this.checked);
});
});
</script>
{{ form_widget(form) }}
<div id="submit">
<input type="submit" class="addnew-submit" />
</div>
</form>
{% endblock %}
Thanks in advance!
Your issue is this line in your controller:
$form = $this->createForm(new PressreleaseType(), array($pr , $years) );
If your form is based on an entity then you can bind the entity to the form by just passing the object on it's own like so:
$form = $this->createForm(new PressreleaseType(), $pr);
If it's a more complicated form then your array needs to be key value with the form field names as the keys. For example (you may have to substitute the actual field names if they differ as we cannot see your form class):
$form = $this->createForm(
new PressreleaseType(),
array(
'press_release_name' => $pr->getName(),
'years' => $years
)
);
EDIT:
It's possible that both of those values are needed in the constructor of the form class if it has been customised so if the above doesn't help you then please add your form class code.

Why did I get a string with when binding a request with Symfony2?

I'm trying to update an object:
public function editAction(Artist $artist)
{
if (!$artist) {
throw $this->createNotFoundException('Unable to find Artist entity.');
}
// We create the form from the external re-usable form made in TestBundle/Form/artist.php
$form = $this->createForm( new ArtistType, $artist);
// We get the request type
$request = $this->get('request');
// If it is a POST request, the user validated the form
if ($request->isMethod('POST')) {
// We make the link Request <-> Form
// Now, $request = Values entered by the user
$form->bind($request);
// We validate the values
if ($form->isValid()) {
// We save $artist in the DB
$em = $this->getDoctrine()->getManager();
$em->persist($artist);
$em->flush();
$this->get('session')->getFlashBag()->add('info', 'Artist edited successfully');
// Everything is fine, we redirect the user
return $this->redirect($this->generateUrl('ymtest_Artist'));
}
}
// We pass the createView() form method to the viexw so that it can print the form if the user arrived on this page with a GET method (he didnt validate the form yet)
return $this->render('YMTestBundle:Musician:edit.html.twig', array(
'form' => $form->createView(),
'artist' => $artist
));
}
But when I'm validating the form, I get an exception:
Expected argument of type object or array, string given
My form looks like this:
{# src/YM/TestBundle/Resources/views/Musician/add.html.twig #}
{% extends "YMTestBundle::layout.html.twig" %}
{% block bodyAdmin %}
<div class="container">
<form action="{{ path('ymtest_EditArtist', {'id': artist.id}) }}" method="post" {{ form_enctype(form) }}>
<div class="row">
{% if form_errors(form)|length != 0 %}
<div class="span12 alert alert-error" style="margin-left:0px">
{# Les erreurs générales du formulaire. #}
{{ form_errors(form) }}
</div>
{% endif %}
</div>
<div class="row">
<div class="span10 BoxesW">
<div>
{{ form_label(form.name, "Artist Name") }}
{{ form_errors(form.name) }}
{{ form_widget(form.name) }}
</div>
<div>
{{ form_label(form.biography, "Artist Biography") }}
{{ form_errors(form.biography) }}
{{ form_widget(form.biography, {'attr':{'class': 'span10' }, 'id': 'wysiwyg' }) }}
</div>
{{ form_rest(form) }}
</br>
<div>
<input type="submit" class="btn btn-primary" />
</div>
</div>
</div>
</form>
</div>
{% endblock %}
And the route is correct since I get the form before validating it.
Thanks for your help
UPDATE:
Here is My new controller:
<?php
namespace YM\TestBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Doctrine\ORM\EntityRepository;
use YM\TestBundle\Entity\Artist;
use YM\TestBundle\Form\ArtistType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
class MusicianController extends Controller
{
/**
* #Route("/Artist/edit/{id}")
* #ParamConverter("artist", class="YMTestBundle:Artist")
*/
public function editAction(Artist $artist)
{
if (!$artist) {
throw $this->createNotFoundException('Unable to find Artist entity.');
}
// We create the form from the external re-usable form made in TestBundle/Form/artist.php
$form = $this->createForm( new ArtistType, $artist);
// We get the request type
$request = $this->get('request');
// If it is a POST request, the user validated the form
if ($request->isMethod('POST')) {
// We make the link Request <-> Form
// Now, $request = Values entered by the user
$form->bind($request);
// We validate the values
if ($form->isValid()) {
// We save $artist in the DB
$em = $this->getDoctrine()->getManager();
$em->persist($artist);
$em->flush();
$this->get('session')->getFlashBag()->add('info', 'Artist edited successfully');
// Everything is fine, we redirect the user
return $this->redirect($this->generateUrl('ymtest_Artist'));
}
}
// We pass the createView() form method to the viexw so that it can print the form if the user arrived on this page with a GET method (he didnt validate the form yet)
return $this->render('YMTestBundle:Musician:edit.html.twig', array(
'form' => $form->createView(),
'artist' => $artist
));
}
}
EDIT
We found in the chat that the problem was in the entity annotations.
#Assert\Valid() was used on a string variable.
You have this action="{{ path('ymtest_EditArtist', {'id': artist.id}) }}" that I suppose generates an url like editArtist/1234 (so passing a string).
And then you have this public function editAction(Artist $artist) that's requiring an object of type Artist.
You should change it to something like:
public function editAction($artistid)
{
$em = $this->getDoctrine()->getManager();
$artist= $em->getRepository('YourBundle:Artist')->find($artistid);
if (!$artist) {
throw $this->createNotFoundException('No artist found for id '.$artistid);
}
//Do whatever you want
}
Remark: You don't need to call $em->persist($artist); when updating an object (http://symfony.com/doc/current/book/doctrine.html#updating-an-object).

Categories