I am using this twig and standalone symfony form and validator component:
use Symfony\Component\Validator\Constraints as Assert;
// other use lines ommitted to shorten the code.
$defaultFormTheme = 'bootstrap_4_horizontal_layout.html.twig';
$csrfGenerator = new UriSafeTokenGenerator();
$csrfStorage = new NativeSessionTokenStorage();
$csrfManager = new CsrfTokenManager($csrfGenerator, $csrfStorage);
$formEngine = new TwigRendererEngine([$defaultFormTheme], $twig);
$twig->addRuntimeLoader(new FactoryRuntimeLoader([
FormRenderer::class => function () use ($formEngine, $csrfManager) {
return new FormRenderer($formEngine, $csrfManager);
},
]));
$twig->addExtension(new FormExtension());
$translator = new Translator('fr_FR');
$translator->addLoader('php', new \Symfony\Component\Translation\Loader\PhpFileLoader());
$translator->addResource('php', ROOT.'/translations/messages.fr.php', 'fr_FR');
$twig->addExtension(new TranslationExtension($translator));
$validator = Validation::createValidator();
$formFactory = Forms::createFormFactoryBuilder()
->addExtension(new CsrfExtension($csrfManager))
->addExtension(new ValidatorExtension($validator))
->getFormFactory();
$form = $formFactory->createBuilder(FormType::class, null, ['csrf_protection' => false])
->add('firstnameEn', TextType::class, [
'constraints' => [new Assert\Length(['min' => 3])]
])
->add('lastnameEn', TextType::class)
->add('email', EmailType::class)
->add('birthDate', TextType::class)
->add('password', PasswordType::class)
->add('applyCard', CheckboxType::class)
->add('showPhoto', CheckboxType::class)
->add('privacyRead', CheckboxType::class)
->getForm();
$request = Request::createFromGlobals();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$errors = $form->getErrors();
var_dump($errors);
$data = $form->getErrors();
var_dump($data);
print("debug pring");
} else {
$errors = $form->getErrors();
var_dump($errors);
$data = $form->getErrors();
var_dump($data);
print("debug pring");
}
echo $twig->render('signup.html',
['form' => $form->createView(),
'title' => 'title',
]);
I am getting
Expected argument of type "null", "Symfony\Component\HttpFoundation\Request" given
that is because of
$form->handleRequest($request);
Why am I getting this error and how to fix it? when I use just
$form->handleRequest();
it works, but of course then form validation is not working. How to fix it? What should I pass to its constructor? I I didn't want to use its isSubmitted() if clause and had no need to validate it and I wanted to use just to output the form it was working fine. The problem appeared when I wanted to use HTTFoundation to use isSubmitted if clause. What should I do?
The Form component uses request handlers (symfony docs) to handle requests in the handleRequest() method. From the linked documentation:
To process form data, you'll need to call the handleRequest() method:
$form->handleRequest();
Behind the scenes, this uses a NativeRequestHandler object to read data off of the correct PHP superglobals (i.e. $_POST or $_GET) based on the HTTP method configured on the form (POST is default).
If you want to use the Request object from the HttpFoundation, you might want to configure the Form component to us the HttpFoundationRequestHandler instead. In that case, you have to pass the $request argument to the handleRequest() method.
Related
I am trying to persist an object of an entity to the database using symfony forms. The entity has an constructor therefore I am giving the object dummy data but I am not able to change this data with the forms. Does anyone have a solution how to create an object that requires a constructor?
public function new(Request $request)
{
$player = new Player("Dummy",0);
$form = $this->createFormBuilder($player)
->add('name', TextType::class)
->add('points', IntegerType::class)
->add('save', SubmitType::class, array('label' => 'Create Player'))
->getForm();
$form->handleRequest($request);
$data = $form->getData();
$name = $data->getName();
error_log($name);
$this->PlayerRepository->store($player);
return $this->render('default/new.html.twig', array(
'form' => $form->createView(),
));
}
$name has always the value "Dummy" no matter what I type in the form.
You save $player here:
$this->PlayerRepository->store($player);
But your actual player data from form is in $data, and this $data should be stored:
$this->PlayerRepository->store($data);
Okay, seems that I found the mistake.
I did not define the POST Route for the same controller building the view.
sorry for that :)
I want to process a form in a separate controller. While the Symfony docs show how to change a form's action and method, they don't show how the controller selected in $form->setAction() is actually supposed to handle the form. Is it present in Request? Do we make another Form object so we can check $form->isSubmitted() and $form->isValid()?
It's a pretty glaring omission.
Here is a quick example:
Controller for displaying the form
/**
* #route("/form", name="form_route")
*/
public function formAction()
{
$form = $this->createFormBuilder()
->setAction($this->generateUrl('task_route'))
->setMethod('POST')
->add('task', TextType::class)
->add('dueDate', DateType::class)
->add('save', SubmitType::class)
->getForm();
return $this->render('form.html.twig', [
'form' => $form->createView(),
]);
}
Controller to handle submission
Is it present in Request?
Yes, the form data is in the request.
Do we make another Form object so we can check $form->isSubmitted() and $form->isValid()?
The form has to be recreated so that you can handle and validate the request.
/**
* #route("/task", name="task_route")
*/
public function postAction(Request $request)
{
$form = $this->createFormBuilder()
->add('task', TextType::class)
->add('dueDate', DateType::class)
->add('save', SubmitType::class)
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()){
$task = $form->getData();
/* ... */
}
//render task to view submission
return $this->render('task.html.twig', [
'task' => $task,
]);
}
This does have some duplicate code even when using entities and Symfony's Form Classes, which is why Symfony Docs recommends using the same controller for processing forms.
I'm quite new here, be patient, please.
I'm trying to make notice board project in Symfony2 using FOSUserBundle.
I try to get logged user id to put it into form created with form builder (and then to MySQL database).
One of attempts is:
public function createNoticeAction(Request $request)
{
$notice = new Notice();
$form = $this->createFormBuilder($notice)
->add("content", "text")
->add("user_id","entity",
array("class"=>"FOS/UserBundle/FOSUserBundle:", "choice_label"=>"id"))
->add("isActive", "true")
->add("category", "entity",
array("class" => "AppBundle:Category", "choice_label" => "name"))
->add("save", "submit", array("label" => "Save"))
->getForm();
$form->handleRequest($request);
$em = $this->getDoctrine()->getManager();
$em->persist($notice);
$em->flush();
return $this->redirectToRoute('app_user_showuserpage');
}
I tried many solutions again and again and I get some error.
You already have the user object Symfony > 2.1.x
In you Controller like this:
$userId = $this->getUser()->getId();
...
$notice->setUserId($userId);
$em->persist($notice);
Don't ->add field in you FormBuilder, its not safely. Set this value in you Controller and don't ->add this field in FormBuilder
for symfony 3.2.13
have excelent solution (just because is working, but is dangerous if someone discover it in pure HTML)
1) first build YourFormType class.
add normal field in Forms/YourFormType.php (if not, formbuilder tell you that you passing smth not quite right (too many fields) ; -) )
$builder
->add(
'MyModelAddedById',
HiddenType::class,
[
'label' => 'echhh', //somehow it has to be here
'attr' => ['style' => 'display:none'], //somehow it has to be here
]
);
2) in your controller
public function addSomethingAction(Request $request){
$form = $this->createForm(MyModelFormType::class);
//set field value
$request->request->set("prodModelAddedById", $this->getUser()->getId());
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$product = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($product);
$em->flush();
$this->addFlash('success', 'record was added');
return $this->redirectToRoute('products');
}
return $this->render(
'default.add.form.html.twig',
[
'newprod' => $form->createView(),
]
);
}
explenation:
you are passing a field and variable to formbuilder (settig it already to default value!)
and important thing, becose of BUG in my opinion - you can't in your form type set method:
public function getBlockPrefix()
{
//return 'app_bundle_my_form_type';
}
because
$request->request->set
can't work properly if your POST data from form are in bag (parameterbag)
no entity managers, no services, no listeners...
hope it helps.
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
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.