Under perfect circumstances, a user submits only numbers - no commas, periods, or letters. This is fine for Chrome because Chrome doesn't allow these characters in an integer input. But what about browsers that don't prevent this? If a user decides to put a comma in, Symfony gets unexpected results.
public function Debug4Action(Request $request){
$inquiry = new Inquiry();
$form = $this->createFormBuilder($inquiry)
->add('revenueMin', 'integer');
$form = $form->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
var_dump($form->getData()->getRevenueMin());
return new Response('');
}
return $this->render('render_form.html.twig', array(
'form' => $form->createView(),
));
}
When a user submits the bad input into this var_dump($form->getData()->getRevenueMin());
outputs NULL
.
The Symfony docs describe a process of transforming data after submission by using the addModalTransformer()
method. This seems like it would be a perfect fit for this use case. I have tried to manually scrub out any non numeric characters and continue processing the input.
public function Debug5Action(Request $request){
$inquiry = new Inquiry();
$form = $this->createFormBuilder($inquiry)
->add('revenueMin', 'integer');
/*
* Symfony2 docs recommend using a this to transform the data into something usable.
* More info: http://symfony.com/doc/current/cookbook/form/data_transformers.html
*/
$form->get('revenueMin')->addModelTransformer(new CallbackTransformer(
function($originalInput){
//As far as I know, this isn't relevant, but CallbackTransformer requires two anonymous functions.
return $originalInput;
},
function($submittedValue){
//I don't know if this works on integers - but let's see what happens.
$submittedValue = preg_replace("/[^0-9]/", "", $submittedValue);
return $submittedValue;
}
));
$form = $form->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
var_dump($form->getData()->getRevenueMin());
return new Response('');
}
return $this->render('render_form.html.twig', array(
'form' => $form->createView(),
));
}
However, now we get slightly different results. var_dump($form->getData()->getRevenueMin());
now outputs an empty string. I would guess that this occurs because preg_replace()
returns an empty sting with being used on NULL
.
The final attempt changes the field type to a text input.
public function Debug6Action(Request $request){
$inquiry = new Inquiry();
$form = $this->createFormBuilder($inquiry)
//Notice that the form input is now text.
->add('revenueMin', 'text');
$form->get('revenueMin')->addModelTransformer(new CallbackTransformer(
function($originalInput){
return $originalInput;
},
function($submittedValue){
$submittedValue = preg_replace("/[^0-9]/", "", $submittedValue);
//Cast the string into an int for processing.
return (integer) $submittedValue;
}
));
$form = $form->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
var_dump($form->getData()->getRevenueMin());
return new Response('');
}
return $this->render('render_form.html.twig', array(
'form' => $form->createView(),
));
}
This last attempt returns exactly what I need to process the submission! var_dump($form->getData()->getRevenueMin());
outputs int(1234)
. However, because I've rendered the form as text instead of integer, I am missing out on some of the HTML5 form elements that would have been built had I built the form with an integer type.
How can I display an integer form input to users but continue to get sanitized integers to process?
答案 0 :(得分:1)
Upon further research it looks like some browsers (I'm working with Safari) will not send anything in a field if the input requires an integer value and an integer is not provided.
Consider the following code:
<!--test.html-->
<form name="form" method="post" action="test2.php">
<label>revenueMin</label>
<input type="number" id="form_revenueMin" name="form[revenueMin]"/><br />
<input type="submit" />
</form>
<?php
//test2.php
var_dump($_POST);
?>
Inputting 1,234 results in:
array(1) { ["form"]=> array(1) { ["revenueMin"]=> string(0) "" } }
Inputting 1234 results in:
array(1) { ["form"]=> array(1) { ["revenueMin"]=> string(4) "1234" } }
Because this is a browser issue and not a Symfony issue, the only solution is the third solution provided in the question.
Also worth noting, the second input still gets sent as a string, so casting it as an integer manually is still required.