I have user.yml file in my validation folder in symfony and I am using it to validate the data. eg:
\APIBundle\Entity\User:
properties:
startDate:
- NotBlank: { message: 'Start date cannot be blank.' }
- Date: { message: 'Enter the valid start date.' }
I wanted to validate "startDate" field if user have passed it which is working now. But if user is not passed the "startDate" then I wanted to skip this validation. i.e Wanted the this validation as optional .
How to achieve this ?
I tried to set required false as following:
\APIBundle\Entity\User:
properties:
startDate:
- Required: false
- NotBlank: { message: 'Start date cannot be blank.' }
- Date: { message: 'Enter the valid start date.' }
Which is not working symfony return the error
required just affects rendering see :
If true, an HTML5 required attribute will be rendered. The corresponding label will also render with a required class.
This is superficial and independent from validation. At best, if you
let Symfony guess your field type, then the value of this option will
be guessed from your validation information.
you should use empty_data in your form like so :
$builder->add('gender', ChoiceType::class, array(
'choices' => array(
'm' => 'Male',
'f' => 'Female'
),
'required' => false,
'placeholder' => 'Choose your gender',
'empty_data' => null
));
Your entity in this case should have the property nullable=true and of course like mentionned NotBlank shouldn't be used
Just remove NotBlank
\APIBundle\Entity\User:
properties:
startDate:
- Date: { message: 'Enter the valid start date.' }
NotBlank is equivalent of reqired.
Since you're using NotBlank, that field is always required. However, you only want to validate the field if it is actually set.
I think that you won't accomplish that with Symfony's built-in validation, but you could write your custom Validation Constraint that handles this case: http://symfony.com/doc/current/cookbook/validation/custom_constraint.html
Related
In my Symfony Application i have a From which contains a lot of checkboxes, radios, textfields and also DateTime Objects.
Everything but the DateTime Objects work fine, but with them i always get the error "Object of class DateTime could not be converted to string"
So i wanted to use this tutorial to change the datetime object to a string.
The thing is i am using a FormFactory and when i use the addModelTransformer()-Method like this...
1st Option:
$form->add($formFactory->createNamed('value', 'date', null, $fieldOptions));
$form->get('value')->addModelTransformer(new CallbackTransformer(
function($dateAsDate){
return $dateAsDate->format('Y-m-d');
},
function ($dateAsString){
return "test"; //TODO: to be changed to make string to date
}
));
...i get the Error "Call to undefined method Symfony\Component\Form\Form::addModelTransformer() "
When i use the builder function outside the Formfactory like this...
2nd Option:
//$builder->addEventListener Stuff is above
$builder->get('value')->addModelTransformer(new CallbackTransformer(
function($dateAsDate){ return $dateAsDate->format('Y-m-d'); },
function ($dateAsString){ return 'null'; } //TODO: to be changed to make string to date
));
...i get the Error "The child with the name "value" does not exist."
Does anybody have an idea how to make this work?
There is no need to use any custom Tranformer here.
The DateType field handles DateTime objects correctly by itself.
You may want to specify some options like 'format' and 'widget' depending on how you want to render your field, but the default 'input' should work fine with DateTime.
For example :
$builder->add('value', DateType::class, [
'format' => 'y-MM-dd',
'widget' => 'single_text', // To have a single input text box
'input' => 'datetime' // This is the default value
];
I have the next form in Symfony 2.7:
$form = $this->createFormBuilder($entity)
->add('laboratorio',null, array('required'=>false)->getForm();
"laboratorio" is a field of type entity. But when I submit the form whitout select a value I got the next error:
An exception occurred while executing
'SELECT n0_.id AS id0, n0_.codigo AS codigo1,
n0_.nombre AS nombre2 FROM nom_laboratorio
n0_ WHERE n0_.id IN (?)' with params [""]:
I think that Symfony should not try to find the entity by his id when the optional field is blank.
Even I try whith $this->submit($request,true) instead of $this->handleRequest($request) in the controller but nothing change.
There is something I am ignoring?
Please try to use the empty_data option.
$form = $this->createFormBuilder($entity)
->add('laboratorio',null, array(
'required' => false,
'placeholder' => 'Choose the laboratorio',
'empty_data' => null,
)->getForm();
In a form, I have the following element:
$email = new Zend_Form_Element_Text('username');
$email
->setLabel($this->getView()->l('E-mail'))
->setRequired(TRUE)
->addValidator('EmailAddress')
->addValidator('Db_NoRecordExists', true,
array(
'table' => 'pf_user',
'field' => 'email',
'messages' => array(
'recordFound' => 'This username is already registered',
)
))
->setErrorMessages(array(
'emailAddressInvalidFormat' => 'You must enter a valid e-mail',
'isEmpty' => 'You must enter an e-mail',
'recordFound' => 'This e-mail has already registered in out database'
));
$form->addElement($email)
the problem is that I always I get the same message "You must enter a valid e-mail" (the first one). Does anybody knows what is the mistake??
Actually, what you're doing is the following :
You set the errors on the element
Zend now thinks that the element did not validate correctly and that the first error is
"You must enter a valid e-mail"
When you display the form, since you set errors, Zend will find them and display the first one it finds. If you switch the order then you'll find that whichever error you put up top will be the error you get.
The more correct way is to set the custom messages in the validator. When the validators are called to validate the element, if the validation fails, the validator will call the setErrorMessages on the element to set the custom errors you specify. Use this type of code below to set your custom messages.
$element->addValidator( array( 'Db_NoRecordExists', true, array(
'messages' = array(
Zend_Validate_Db_Abstract::ERROR_NO_RECORD_FOUND => 'Myy custom no error record',
Zend_Validate_Db_Abstract::ERROR_RECORD_FOUND => 'My custom record error'
)
) ) );
You'll find that usually there are consts in each validator class that specify one type of error. In this case, the consts are in the parent class of the DB_NoRecordExists class but usually you'll find them directly in the class near the top.
Basically by passing 'true' as second parameter to addValidator() you are saying the validator to break the chain whenever validator fails . Since "" is not an valid email address hence the first email validator fails and breaks the chain
From Zend Doc http://framework.zend.com/manual/en/zend.validate.validator_chains.html
In some cases it makes sense to have a validator break the chain if
its validation process fails. Zend_Validate supports such use cases
with the second parameter to the addValidator() method. By setting
$breakChainOnFailure to TRUE, the added validator will break the chain
execution upon failure, which avoids running any other validations
that are determined to be unnecessary or inappropriate for the
situation. If the above example were written as follows, then the
alphanumeric validation would not occur if the string length
validation fails:
$validatorChain->addValidator(
new Zend_Validate_StringLength(array('min' => 6,
'max' => 12)),
true)
->addValidator(new Zend_Validate_Alnum());
In my Zend framework I have two row one rows contains state dropdown with label state and the other contains a text box with label other state. Below is the code:
'state' => array('select', array(
'required' => true,
'decorators' => $elementDecorators,
'label' => 'State:',
'multiOptions' => $values["state"]
)),
'other_state' => array('text', array(
'required' => true,
'filters' => array('StringTrim'),
'decorators' => $elementDecorators,
'label' => 'Other State:',
'class' => 'other_state',
))
Here the other state is set as required. I need it required only when the user select "Other" value from the state drop down.
Client Side:
jQuery solution:
Showing your HTML output would have been a help here. But the following will add the attribute required if other is selected - this will also enable the input and disable it so the user can only enter something in other state, if they select other:
$("#state").change(function(){
if ($(this).val() == "other"){
$("#other_state").removeAttr("disabled");
$("#other_state").attr("required", "required");
}
else {
$("#other_state").removeAttr("required");
$("#other_state").attr("disabled", "true");
}
});
See a demo here
The above will do the validation on the clients side - with jQuery, however if the user has javascript turned off, it would allow the user to select other and leave other_state blank!
Server Side:
Zend solution:
What you should also do is add some validation to the zend_form. However, you can't add them the normal way - if you added a validator to say other_state can't be empty - you would have an error when a state is selected and you want it to be empty.
In your form class you could override the isValid call to add your custom validation, see the discussion here: There is another example on how to do this here
/**
/* override the isValid function of Zend_Form
/* to set a required field based on a condition
*/
public function isValid($value) {
// Check the key exists in the stack, and if its set to other:
if (array_key_exists('state', $value) && $value['state'] == 'other') {
// It is so make sure other_state is a required field:
$this->other_state->setRequired(true);
}
parent::isValid($value);
}
Say I create a text element like this:
$firstName = new Zend_Form_Element_Text('firstName');
$firstName->setRequired(true);
Whats the best way to change the default error message from:
Value is empty, but a non-empty value
is required
to a custom message? I read somewhere that to replace the message, just use addValidator(..., instead (NO setRequired), like this:
$firstName = new Zend_Form_Element_Text('firstName');
$firstName->addValidator('NotEmpty', false, array('messages'=>'Cannot be empty'));
but in my testing, this doesn't work - it doesn't validate at all - it will pass with an empty text field. Using both (addValidator('NotEmp.. + setRequired(true)) at the same time doesn't work either - it double validates, giving two error messages.
Any ideas?
Thanks!
An easier way to set this "site-wide" would be to possibly do the following in a bootstrap or maybe a base zend_controller:
<?php
$translateValidators = array(
Zend_Validate_NotEmpty::IS_EMPTY => 'Value must be entered',
Zend_Validate_Regex::NOT_MATCH => 'Invalid value entered',
Zend_Validate_StringLength::TOO_SHORT => 'Value cannot be less than %min% characters',
Zend_Validate_StringLength::TOO_LONG => 'Value cannot be longer than %max% characters',
Zend_Validate_EmailAddress::INVALID => 'Invalid e-mail address'
);
$translator = new Zend_Translate('array', $translateValidators);
Zend_Validate_Abstract::setDefaultTranslator($translator);
?>
Give this a shot:
$firstName = new Zend_Form_Element_Text('firstName');
$firstName->setLabel('First Name')
->setRequired(true)
->addValidator('NotEmpty', true)
->addErrorMessage('Value is empty, but a non-empty value is required.');
The key is that "true" on the validator if you set that to true, it'll kill the other validations after it. If you add more than one validation method, but set that to false, it will validate all methods.
Zend_Form sets the required validation error as 'isEmpty', so you can override its message using setErrorMessages(). For example:
//Your Required Element
$element->setRequired(true)->setErrorMessages(array(
'isEmpty'=>'Please fill this field'
));
It worked for me, using ZF 1.11
Try
->addValidator('Digits', false);
or
->addValidator('Digits');
You assume that to check Digits it has to have a string length anyway.
Also, I like to do some custom error messages like this:
$firstName->getValidator('NotEmpty')->setMessage('Please enter your first name');
This allows you to "get" the validator and then "set" properties of it.
Try the following.
$subjectElement->setRequired(true)->addErrorMessage('Please enter a subject for your message');
This worked form me.
But try this:
$firstName->setRequired(true)
->addValidator('NotEmpty', false, array('messages' => 'bar'))
->addValidator('Alpha', false, array('messages'=>'Must contain only letters'));
If left empty and submitted, itll give two messages bar & '' is an empty string. Its that second message thats coming from setRequired(true) thats the problem
if you put:
$element->setRequired(false);
the validations don't work at all, you have to define:
$element->setAllowEmpty(false);
in order to get the correct behavior of the validations.
Try this..
$ausPostcode = new Zend_Form_Element_Text('aus_postcode'); $ausPostcode->setLabel('Australian Postcode')
->setRequired(true)
->addValidator('StringLength', false, array(4, 4))
->addValidator(new Zend_Validate_Digits(), false)
->getValidator('digits')->setMessage('Postcode can only contain digits');
This sets the custom error message only for the Digits validator.
One small issue. This code:
$zipCode->setLabel('Postal Code')
->addValidator('StringLength', true, array( 5, 5 ) )
->addErrorMessage('More than 5')
->addValidator('Digits', true)
->addErrorMessage('Not a digit');
Will generate both error messages if either validation fails. Isn't is supposed to stop after the first fails?
use a zend translator with zend_validate.php from
ZendFramework-1.11.3\resources\languages\en\Zend_Validate.php and then modify this file how you need
and then modify it accordingly to your needs