Call to undefined method isMethod on Symfony2 - php

Here is my problem I'm following the symfony tutorial (Handling form submission) but I've the error "Call to undefined method Symfony\Component\HttpFoundation\Request::isMethod()" and I can't fix it.
I read in some website that isMethod was suppressed, but I can't find another way to perform my check.
Thanks.
use Symfony\Component\HttpFoundation\Request;
public function contactusAction(Request $request)
{
$contact = new ContactUs();
$form = $this->createFormBuilder($contact)
->add('nom', 'text')
->add('mail', 'email')
->add('sujet', 'choice', array('choices' => array('pt' => 'Problemes techniques', 'bi' => 'Boite a idees', 'd' => 'Divers')))
->add('msg', 'textarea')
->getForm();
if ($request->isMethod('post'))
{
$form->bind($request);
if ($form->isValid())
{
echo 'OK!';
//return $this->redirect($this->generateUrl('task_success'));
}
else
echo 'KO!!';
}
return $this->render('MyCoreBundle:Info:contactus.html.twig', array('form' => $form->createView()));
//return array();
}}

Update Symfony to the recent version or use
if ('POST' === $request->getMethod())
Also, be aware that the compared method string should be in uppercase.

Related

Symfony: ManyToOne Form Issue

I have two entities called, Ticket & TicketUpdate.
Each Ticket can have many TicketUpdates, but every TicketUpdate can only have 1 Ticket.
Next I have a form which shows the current Ticket, but also allows me to add 1 TicketUpdate & change attributes of Ticket.
This is my controller:
//TicketController.php
...
/**
* #Route("/ticket/{id}", name="app_ticket")
*/
public function ticket(Request $request, Ticket $ticket)
{
$ticketUpdate = new TicketUpdate();
$ticketUpdate->setTicket($ticket);
$form = $this->createForm(TicketUpdateType::class, $ticketUpdate); //custom form type
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($ticketUpdate);
$em->persist($ticket);
$em->flush();
}
return $this->render('ticket/view.html.twig', ['ticket' => $ticket, 'form' => $form->createView()]);
}
...
TicketUpdateType:
//TicketUpdateType.php
...
class TicketUpdateType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('text', TextareaType::class, ['label' => 'update', 'required' => false, 'attr' => ['class' => 'textarea-sm'])
->add('ticket', TicketType::class, ['label' => false, 'by_reference' => false]) //custom Type for Tickets
->add('submit', SubmitType::class, ['label' => 'save']);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => TicketUpdate::class
]);
}
}
...
However, this solution does not work for me. Symfony always wants to create a new Ticket entry, instead of changing the old one.
Is there any way to fix this?
May you know, a magic with symfony forms, with you can get an Entity (Ticket), like in your example, I dont know... but this will working:
/**
* #Route("/ticket/{ticketId}", name="app_ticket", requirements={"ticketId"="\d+"})
*/
public function ticket(Request $request, int $ticketId = 0)
{
$em = $this->getDoctrine()->getManager();
$ticket = $em->getRepository(Ticket::class)
->findOneBy([
'id' => $ticketId
]);
if ($ticket instanceof Ticket === false)
{
die('Ticket dont exist with the requested ID.'); #Just return here some error message
}
$ticketUpdate = new TicketUpdate();
//Because your setTicket() setter inside your TicketUpdate Entity
//sure have nullable typehinted argument (?Ticket $ticket)
//if this is a valid doctrine relationship
//(but if i'm wrong, please show the touched parts of your TicketUpdate entity)
$ticketUpdate->setTicket($ticket); #<-- here is an "old" Ticket $ticket
$form = $this->createForm(TicketUpdateType::class, $ticketUpdate); //custom form type
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
$em->persist($ticketUpdate);
//I'm working a lot with doctrine relationships
//In many time necessary using a setter in the both Entity
$ticket->addTicketUpdate($ticketUpdate); #You know this setter! Change, if my tip wrong
$em->persist($ticket);
$em->flush();
}
return $this->render('ticket/view.html.twig', [
//Now, this is an instance of the Ticket
//not an int ID!
//so if you need the ID, you can get in twig, like:
//{{ ticket.id }}
'ticket' => $ticket, #Or: $ticket->getId()
'form' => $form->createView()
]);
}
The requirements inside the #route means, the method will running only on pages, where the {ticketId} is numeric.
Update: I changed by_reference to true and removed every logic in my TicketType, which seemed to cause the issue.
Atleast for now I got it running. Here is my controller:
//TicketController.php
...
/**
* #Route("/ticket/{id}", name="app_ticket")
*/
public function ticket(Request $request, Ticket $ticket)
{
$ticketUpdate = new TicketUpdate();
$ticketUpdate->setTicket($ticket);
$form = $this->createForm(TicketUpdateType::class, $ticketUpdate); //custom form type
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($ticketUpdate);
//$em->persist($ticket); -> removed, will be automatically updated by symfony
$em->flush();
}
return $this->render('ticket/view.html.twig', ['ticket' => $ticket, 'form' => $form->createView()]);
}
...

Symfony API Request Unexpected "G"

I'm really thrown off by this error I get when posting to Google Books API. The last response in this function is triggered when I post 1781100489 to a form. This form then runs resultAction function. Instead of returning what I want it to, I get a JSON.parse error with an unexpected token in line 1 column 1.
When tested with Postman, it gives me this peculiar message in its response Unexpected 'G'. What could this mean? I have been dumping the variable as you can see, it's commented, but can't understand why this is occuring.
Any clues?
public function findAction(Request $request)
{
$form = $this->createFormBuilder(null, ['csrf_protection' => false])
->add('Title', TextType::class)
->add('Search', SubmitType::class)
->getForm();
$form->handleRequest($request);
if($form->isValid()){
$json = file_get_contents("https://www.googleapis.com/books/v1/volumes?q=".$form->get('Title')->getData());
$response = json_decode($json, true);
if(array_key_exists('items', $response)){
return $this->render('BlogsiteBooksBundle:Pages:results.html.twig', [
'items' => $response['items']
]);
} else {
return new Response('Google did not have any items', 400);
}
}
//var_dump($request);
return new Response('Google Book Not Found', 404);
}
Your request is not related to the form, build the form using Symfony form component in the controller, and manually in the twig, then parameters names does not match. The $form->handleRequest($request); can't find the title, because expect a parameter called form[Title] and you are passing only Title.
Solutions:
1 - Submit manually all given parameters in the query
Change:
$form->handleRequest($request);
For this:
$form->submit($request->query->all());
2 - Change the name of the input to match with symfony expected name and the method used should be POST:
<form action="app_dev.php/find" method="post">
<input type="text" name="form[Title]" id="Title" value="">
<input type="submit" value="Search">
</form>
3 - Render your form using twig form to avoid this problems
Controller:
/**
* #Route(name="find", path="/find")
*/
public function findAction(Request $request)
{
$form = $this->createFormBuilder(null)
->add('Title', TextType::class)
->add('Search', SubmitType::class)
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$json = file_get_contents("https://www.googleapis.com/books/v1/volumes?q=".$form->get('Title')->getData());
$response = json_decode($json, true);
if (array_key_exists('items', $response)) {
return $this->render(
'BlogsiteBooksBundle:Pages:results.html.twig',
[
'items' => $response['items'],
]
);
} else {
$form->addError(new FormError('Google did not have any items'));
}
}
return $this->render('find.html.twig', ['form' => $form->createView()]);
}
View find.html.twig:
{{ form(form) }}
Note: each point is a possible solution, use only one of them, the third is the recommended for simple Symfony forms.
I was dealing with the same error in POSTMAN. I searched for answers but nothing was satisfying my problem.
I find by self that their is a statement "exit();" in my PHP file. I removed it & my problem was solved. I hope my solution help someone.

Symfony 2 form choice field fails validation on POST (no data class)

Here is the form in controller action:
$form = $this->get('form.factory')->createNamedBuilder('meetings_form', 'form', $defaults)
->add('list','choice',array(
'choices' => array('1'=>'val1','2'=>'val2'),
'required' => false
))
->add('agency','text')
->add('name','text')
->add('phone','text')
->add('email','email')
->add('type','hidden')
->getForm();
Here is another action that handles POST
public function wsFormPostAction(Request $request)
{
if ('POST' == $request->getMethod()) {
$form = $this->get('form.factory')->createNamedBuilder('meetings_form', 'form')
->add('list', 'choice',array(
'choices' => array()
))
->add('agency', 'text')
->add('name', 'text')
->add('phone', 'text')
->add('email', 'email')
->add('type', 'hidden')
->getForm();
$form->bind($request);
if ($form->isValid()) {
$data = $form->getData();
} else {
$errors = $form->getErrorsAsString();
var_dump($errors);
}
}
}
And here is what I get:
list: ERROR: This value is not valid
agency: No errors
name: No errors
phone: No errors
email: No errors
type: No errors
There are no examples at all with choice fields without specifying data_class. It seems to be simple task, but I can't solve it. Why does it fails validation?
You pass 'choices' => array(). This means, that no choice is valid.
Your main problem is that there's different code for creating the same form. You should use FormType and register it, this way you can use form builder with string argument instead of form in any place you need it.
Another common pattern is to use the same controller action for showing and processing the form. If there are some errors in the form, you don't need to redirect, besides, after redirect you would not be able to insert the values that were typed in the previous page.

Symfony2 form - how overwrite field with default value

I have a form with one default value:
class GearType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('options')
->add('model', 'choice', array('choices' => $this->getModelChoices(), 'data' => 2));
}
one of the requirements is form can be pre-populated by re-sellers by passing parameters in URL. It is also nice feature for potential customers to copy and paste link to email, communicators, etc.
I did it this way:
/**
* #Route("/car/gear")
* #Template()
*/
public function gearAction(Request $request)
{
$form = $this->createForm(new GearType());
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
return 'is valid';
}
} else {
$get = $this->getRequest()->query->all();
if (!empty($get)) {
$normalizer = new GetSetMethodNormalizer();
$form->setData($normalizer->denormalize($get, new Gear())); # look here
}
}
return array('form' => $form->createView());
}
unfortunately field 'options' has always default value, instead value passed as a parameter.
I have tried to change line # look here into
$gear = $normalizer->denormalize($get, new Gear());
$form = $this->createForm(new GearType(), $gear);
but no result.
It seems that solution is passing additional parameter to GearType object. I do not like this solution. Does anyone know better way?
Add this snippet, and modifiy between the [ ] as appropriate
$form->bind($request);
if ( [ passed parameters from querystring ] ){ //// New Code
$form->getData()->setOptions( [ processed parameter ]); //// New Code
} //// New Code
if ($form->isValid()) {
return 'is valid';
}
The reason for the field options always having default value may be the actual query. Instead of denormalizing and setting the data directly, modify else fragment to:
} else {
$form = $this->createForm(new GearType(), new Gear(), array(
'validation_groups' => array('not-validating')
));
$form->bind($request);
}
The form will validate only against validations associated with the not-validating group, which will avoid showing the common required alerts if the form is built form GET.
Docs about 'validations-groups': http://symfony.com/doc/current/book/forms.html#validation-groups
The question is similar to: Entity form field and validation in Symfony2?

How to render a form without a class in other service?

I want to generate a class-less form inside my service.
The way I do it is:
class StepSummary implements StepInterface
{
public function __construct($container)
{
$this->container = $container;
}
public function getVariables()
{
$form = $this->container->get('form.factory')->createBuilder('text')
->add('accept')
->getForm();
return array('form' => $form->createView());
}
}
In the API, I've found that I need to pass a form type to the FormBuilder - I didn't find any reference to that, so I've put imaginary text string. Now it renders the form but this way:
<input type="text" id="text" name="text" required="required" />
Obviously there is no reference to the accept field.
Controller's createForm() method was quite helpful here:
public function createFormBuilder($data = null, array $options = array())
{
return $this->container->get('form.factory')->createBuilder('form', $data, $options);
}
So the solution is:
$form = $this->container->get('form.factory')->createBuilder('form')
->add('accept')
->getForm();
Look at the chapter in the Symfony2 documentation called Using a Form without a Class.
Basically, you have to use createFormBuilder and instead of a string or an object you just pass an array with the default values.
From the documentation mentioned before:
// make sure you've imported the Request namespace above the class
use Symfony\Component\HttpFoundation\Request
// ...
public function contactAction(Request $request)
{
$defaultData = array('message' => 'Type your message here');
$form = $this->createFormBuilder($defaultData)
->add('name', 'text')
->add('email', 'email')
->add('message', 'textarea')
->getForm();
if ($request->getMethod() == 'POST') {
$form->bind($request);
// data is an array with "name", "email", and "message" keys
$data = $form->getData();
}
// ... render the form
}
If you don´t want to tie your form to any particular object, you don´t need to pass any object to the builder, you can do:
$form = $this->container->get('form.factory')->createBuilder()
->add('accept')
->getForm();
If you want to set some defaults for the form, you can tie the form to an array. For example:
$data['accept'] = 'default accept';
$form = $this->container->get('form.factory')->createBuilder($data)
->add('accept')
->getForm();

Categories