Disable auto translation for input values in Symfony 2 - symfony

Symfony2 automatically translate the input field values with type decimal or integer.
I have a two languages for my app: arabic and english
I created an Entity with the following field:
/**
* #var float $price
*
* #ORM\Column(name="price", type="decimal", scale=2, nullable=true)
*
* #Assert\Regex(pattern="/^[0-9]+(\.\d{1,2})?$/",message="Incorrect price.")
* #Assert\Type(type="float")
* #Assert\Min(0)
*/
private $price;
In form I let the sf to guess a field type:
$builder->add('price')
I load the form for editing this entity in Arabic Interface.
In the price field I see ١٢٫٤ instead of 12.40.
I can't save the form because HTML5 validation is failed.
If I enter 12.40 in the current field and save Entity, 12 will be saved, instead of 12.40.
Why? How to disable it? how to validate the Arabic digits?
Any suggestions?
EDIT: solved, see below

I found the answer why it happens here
As you can see, symfony register a ViewTransformer for these widget types:
$builder->addViewTransformer(
new IntegerToLocalizedStringTransformer(
$options['precision'],
$options['grouping'],
$options['rounding_mode']
));
Current transformer transform an integer value to localized string. It happens for the number widget (NumberToLocalizedStringTransformer) and money widget (MoneyToLocalizedStringTransformer) too.
So I think need to register a new FieldType which will not used a ViewTransformer.
EDIT: I solved the problem just disabling intl extension and now all numeric fields are using a default english numbers. If you enable the intl extension you should use only localized numbers in the input values, it's a default behavior.

This is an old post, but i hope my answer will help anyone encounters this issue.
Instead of disabling intl extension as suggested above, you can use Data Transformers in form type to manually set the default locale to English and that will let the fields to be shown with English digits.
1) Use Data Transformers to interrupt (hook into) the process of showing the field data.
2) Manually set Locale to English.
here is what i've done with dateOfBirth field in the form type:
$builder -> add(
$builder -> create(
'dateOfBirth', DateType::class, array(
'label' => 'Date of Birth',
'widget' => 'single_text',
'required' => false,
'html5' => false,
'attr' => ['class' => 'form-control']
)) -> addModelTransformer(new CallbackTransformer(
function($dateOfBirth) {
\Locale::setDefault('en');
return $dateOfBirth;
},
function($dateOfBirth) {
return $dateOfBirth;
}
))
);

Related

What does the constraint Required do?

What does the constraint Required do in the form builder? If a field was not submitted (not empty value!), I don't receive a corresponding error message. This field is just ignored.
$builder
->add('firstname', TextType::class, [ 'constraints' => [new NotBlank()], 'required'=>true])
->add('lastname', TextType::class, [ 'constraints' => [new NotBlank(),] ,'required'=>true])
How can say, that the field always MUST be submitted?
Thank you.
Required mean your field need a value tu be be submitted. It's similar to the HTML behaviour.
EDIT:
https://symfony.com/doc/current/reference/forms/types/form.html#constraints
https://symfony.com/doc/current/form/without_class.html#form-option-constraints
The issue is on your constraints, I don't know for sure but if adding those to your form don't fix your problem, have a look att adding assert to your Entity attached to your form
https://symfony.com/doc/current/reference/constraints/NotBlank.html
Then validate this entity in your controller
https://symfony.com/doc/current/validation.html
And relying on this you might add errors to the form.
A colleague has found the solution:
In the related entity, you need to define a callback-function like this:
/**
* Check bank account by "CUSTOMER" - not null
* Because NotNull() not working in form type!
* #Assert\Callback()
*/
public function validateBankaccount(ExecutionContextInterface $context)
{
if ($this->type == self::TYPE_CUSTOMER && is_null($this->bankAccount)) {
$context->buildViolation('Bank account is required!')
->atPath('bankAccount')
->addViolation();
}
}

Require a field in symfony2 server side

I have a form in Symfony2 which I am building with buildForm
I add constraints like so,
$builder
->add('firstName', 'text', [
'required' => true,
'constraints' => [
new NotBlank(),
],
]
)
Everything works fine until I delete the input from my html and submit it without the firstName. I don't get any errors and it submits normally. Is there a way to absolutely require the firstName, even if is not present in the submit data
You must use an assert with your entity as explained in the symfony documentation here
like this:
class User
{
/**
* #orm:Column(type="string", nullable=false)
* #assert:NotBlank
*/
private $firstname;
}
You did not submit any data, the form is not submitted hence no validation is triggered.
Instead of:
$this->handleRequest($request);
Try to always submit the form even if the data is missing:
$form->submit($request->request->all());
I cannot guarantee this code is valid in your context since you did not provide your controller code.

Show decimal percent type field

I'm trying to show a form which has a percent type field that can show values like 3.03% for exemple. But it seems to be rounding to integers, e.g 3% in this case.
Entity field :
/**
* #var float
* #ORM\Column(type="float")
*/
private $penaltyRate;
Form builder :
...
->add('penaltyRate', PercentType::class, ['label' => 'create.form.penalty'])
Is this a limitation of percentType and should I just use another type and add manually the '%' indicator ?
EDIT
For future googler, while #Emanuel Oster was right for just pointing to the official symfony documentation, as it wasn't obvious for me the first time I read it here is an example if you want to allow two decimals :
Form builder :
...
->add('penaltyRate', PercentType::class, [
'label' => 'create.form.penalty',
'scale' => 2
])
From the symfony documentation:
scale
type: integer default: 0
By default, the input numbers are rounded. To allow for more decimal
places, use this option.
Try This
->add('penaltyRate', PercentType::class,[
'label_format' => 'penaltyRate',
'scale'=>1, // or 'scale'=>2
'type'=>'integer'
])

Symfony won't accept dates between 12/12/any year - 31/12/any year

Symfony won't accept dates between 12/12/any year - 31/12/any year as date and produce error below.
DateTime::__construct(): Failed to parse time string (31/12/1111) at position 0 (3): Unexpected character
Any reason why?
Note: Some will ask why I don't use line below. I don't use because I don't want form validation errors coming from form type. I'm purely reliying on annotations. If anyone knows how to by-pass form validation errors coming from form type then I'm happy to lear and use it instead.
$builder->add('year', 'date', array('widget' => 'single_text', 'format' => 'dd/MM/yyyy'));
Cars Entity:
/**
* #var date
* #ORM\Column(type="date")
* #Assert\NotBlank(message="The Year field is required.")
*/
protected $year;
Form type:
->add('year', 'text', array('label' => 'Year'))
Controller
$cars->setYear(new \DateTime($formdata->getYear()));
According to the documentation, you should change this line
$cars->setYear(new \DateTime($formdata->getYear()));
to this
$cars->setYear(\DateTime::createFromFormat('j/m/Y', $formdata->getYear()));

Best practice symfony validation

I'm asking myself about the validation when an user sends a form... I saw the documentation and a tutorial. They explain 2 ways to valid datas:
Documentation:
You have to create the file:
/Resources/config/validation.yml
Then add something like that:
Acme\BlogBundle\Entity\Author:
properties:
name:
- NotBlank: ~
Tutorial I saw on Internet:
They add constraints directly in Entity like:
use Symfony\Component\Validator\Constraints as Assert;
/**
* #var string $title
*
* #ORM\Column(name="title", type="string", length=255)
* #Assert\MinLength(10)
*/
private $title;
There is a best pratice? Should I write all constraints in validation.yml or in my entities? Is it possible to face a form without entity behind?
Benefit from separate file:
You have all constraints in only one file
Benefit from entity file:
You have sql constaints with your form constaints and you have the field type.
So, what should I use? Or no one cares about that?
Edit: I don't find any information about how to add a variable in validation.yml like:
Acme\BlogBundle\Entity\Author:
constraints:
- Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
fields: [name]
message: {{ name }} isn't available
In Entity:
#Assert\UniqueEntity(message='{{ name }} isn't available'
Best regards,
Should I write all constraints in validation.yml or in my entities?
You can, but you don't have to, it is more about personal preference. Personally, I prefer to validate input in my forms, like this:
$builder->add('contactPerson', 'text', array(
'label' => 'Contact person',
'constraints' => array(
new NotBlank(array('message' => 'This field can not be empty.'))
),
'required' => true,
));
Is it possible to face a form without entity behind?
Yes it is, but usually it is better to use entity behind. If you want to leave out the entity behind form, you just remove this line from your form's setDefaultOptions method:
'data_class' => '...'
After submitting the form, you can access form data by using $form->getData().
Benefit from separate file: You have all constraints in only one file
Benefit from entity file: You have sql constaints with your form
constaints and you have the field type.
So, what should I use? Or no one cares about that?
This is more about personal preference. Personally, I prefer to have validation and form in the same time. Searching for the validation in some other file when I want to make a change to some of my fields in form would take me more time.

Resources