UniqueEntity on multiple fields doesn't show an error message - validation

I've added the following constraint to my entity:
* #ORM\Table(name="link", uniqueConstraints={#ORM\UniqueConstraint(name="unique_link_idx", columns={"first_form_id", "first_question_id","last_form_id","last_question_id"})})
* #UniqueEntity(fields={"firstForm", "firstQuestion","lastForm","lastQuestion"}, message="Cette liaison existe déjà !")
* #ORM\Entity(repositoryClass="Ineat\LinkQuestionBundle\Entity\LinkRepository")
The UniqueEntity constraint works well because before adding it, when trying to insert the exact same entity to the DB I had a DBALException abount integrity constraint.
Since then I havn't this exception anymore, the form isn't validating but {{ form_errors(form) }} doesn't print any message.
After having checked in the controller $form->getErrors() returns an empty array while $form->getErrorsAsString() contains the UniqueENtity constraint.
How can I have my UniqueEntity's constraint error message showing

As the UniqueEntity validation seems to fail in one of your child-forms ...
(as the error message is only present in getErrorsAsString and not in getErrors)
... in order to have the child-form errors available in your parent-form use error-bubbling:
$formBuilder->add('child-form','child-form-type', array(
'error_bubbling' => true,
)
)
... or inside your child form:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'error_bubbling' => true,
));
}

Sometimes the issue occurs because the entity isn't binding the error message to the right field. Using the validation.yml file gives you more control over how and where the error message should be treated.
# src/Ineat/LinkQuestionBundle/Resources/config/validation.yml
Ineat\LinkQuestionBundle\Entity\LinkRepository:
constraints:
- Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
fields: [firstForm, firstQuestion, lastForm, lastQuestion]
errorPath: lastQuestion
message: 'This port is already in use on that host.'
More information here : Symfony - UniqueEntity
Also putting text strings into "translation" files is good practice (even if you only use/have one language). You won't have bits of text lying around in your views / entities / forms / controllers ... They will all be in you translation folder, in one location. Duplicate strings can also be changed all at once if necessary. It would look like this :
# src/Ineat/LinkQuestionBundle/Resources/config/validation.yml
Ineat\LinkQuestionBundle\Entity\LinkRepository:
constraints:
- Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
fields: [firstForm, firstQuestion, lastForm, lastQuestion]
errorPath: lastQuestion
message: 'linkquestion.form.errors.unique'
# src/Ineat/LinkQuestionBundle/Resources/translations/validators.fr.yml
linkquestion:
form:
errors:
unique: "This port is already in use on that host."
# Or which ever structure you choose.
Then just tell your application that it will always be in French.

Related

Laravel Request / Validation always return string type values

In laravel 7, the $request->all() or the $validator->valid(), always return an array of values, key assign is correct, but the values are always strings.
I need the validator to transform the field to the rules i made.
Example in rules for validation : ['no' => 'required|integer|min:1',...]
Example of the output of validation->valid() : [ "no" => "1231" ] - string typed, i need this to be integer like : [ "no" => 1231 ]
I dont want to cast every field one by one... what i'm doing wrong ?
NOTE
All the validations works well, it's only the output of the fields that i want to match the validation, if i say the field is integer, the result of the validation must be integer and not string.
I just resolve this problem :
Create a FormRequest file, and put the validations, rules and messages there.
I dont know why... in the last version : my validations , rules and messages stay in the controller file.
Clear cache, everything ok.

Laravel Custom Validation: Show field data of failing record

I need a way to place data of failing record along with count of records that failed because of the same reason. I hope the explanation is enough to get the requirement.
eg:
$rules['inventories.*.activity_id']= [ 'required', 'exists:activities,id ];
$messages['inventories.*.activity_id.required'] = 'Activity id can not be blank.';
$messages['inventories.*.activity_id.exists'] = "Activity id <<< [FAILING RECORD -> ACTIVITY_ID] >>> does not exist in the system. <<< NUMBER OF RECORDS FAILED FOR THIS REASON >>> entries skipped.";
Anyone have an idea about this?
I found I can place :attributes but this does't not what I want.
You could try using the :input attribute to display the value you are checking the existence of in your custom validation message:
'Activity id :input does not exist in the system.'
Though this will not get you to your failure count part.
this shows you number of validation errors:
count($errors)
if you want to show the invalid value that passed among request in the error message, you can do this:
public function messages()
{
return [
'fieldname.numeric' =>
'The :attribute must be numeric. Your value is '.$request->input('fieldname')
];
}

Symfony2 UniqueEntity Validation and custom message

I have a problem with the custom message in the validator.
I use embedded forms and when I save data to DB some embedded form has a value already exists in DB. When constraint prevents save I get the error 'Sprzęt o takim identyfikatorze już istnieje', but I don't know which.
It's possible display in message bad value?
I read the documentation and I found about {{ limit }} for min, max but I can find nothing about UniqueEntity.
AppBundle\Entity\Hardware:
constraints:
- Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
fields: [sn]
message: 'Sprzęt o takim identyfikatorze już istnieje.'
groups: [inventory]

Use Validation in FormType or in Entity / Yaml

Which Differents are when use Validation Entity or in Yaml or in FormType?
form Type
....
->add('email', 'text', array (
'constraints' => array (
new Email(array('message' => 'error Email'))
)
))
....
YAML
properties:
email:
- Email:
message: error Email.
Entity
{
/**
* #Assert\Email(
* message = "error Email",
* )
*/
protected $email;
}
All These methods are the same ?
They are not the same! You mixed up entity validation and form validation:
Entity validation belong to entities. This means that it isn't matter whether the new data come from a form or ajax query or you just set some constant data. Validation is triggered by calling a validation on the entity. Note: entity validation runs on form validation too.
Form validation belong to forms. This means that you can validate form values with them (on calling $form->isValid()). But this can result invalid entities because nothing guarantees that your entities will be consistent (just the forms).
For this reason Symfony recommends using entity validation instead of form validators.
Apart from that, there is no difference among annotation, yml, xml or php format. Only the precedences.
I think they would apply the same validation constraints.
I tend to keep all constraints in validation.yml because in my point of view is the most clean way to do it. Also more compatible with Translations.
But all depends on the context and the project you are working on.
UPDATE: After reading Riska's entry I agree with him. The result at the end is the same, but he has the right point there.
Is there a way to use the same validation.yml so the constraints applied to entites are applied to the formtype as well
for instance, if title field in entity is 50charsm ax length, title field in formttype as well.
so we can avoid specifying max length in the add-method of the formtype.
In summary
how to use entity validation constraint in formtype so same constraitn ( required max length ) etc are auto applied ?

Propel ORM Version 1.6.4 -understanding validators

(reworded the question hours later to be more descriptive)
I need a little advice on understanding Propel setters/validators in a standalone (non-framework) development.
The documentation on validation states:
Validators help you to validate an input before persisting it to the database.
... and in validator messages we can provided coherent advice on where users can correct entries that don't pass Propel validation.
The sample usage of a validator reads:
$user = new User();
$user->setUsername("foo"); // only 3 in length, which is too short...
if ($objUser->validate()) {
...
The problem I have found with this is 'what if you cannot setXXX() in order to validate it?'
I have a column type DATE and I invite a visitor to enter a date in a web form. They mistype the date and submit 03/18/20q2
I would hope that one of my custom validators would be able to report a validator message and return the form once more to the user to be amended, however this occurs first:
Fatal error: Uncaught exception 'PropelException' with message 'Error parsing date/time value: '03/18/20q2' [wrapped: DateTime::__construct() [<a href='datetime.--construct'>datetime.--construct</a>]: Failed to parse time string (03/18/aaa) at position 5 (/):
In my tests I couldn't get any simple or CustomValidator to fire once I'd written (for example):
$event= new Event();
$event->setDateStart($form_value_for_date); // where values is "03/18/20q2"
I understand why this is so - it would not make sense to be able to create and try to manipulate a new object if you cannot rely on its fields, even before you save it.
The dilemma this gives me is:
If a fatal error can result from invalid entry preventing Propel validation from handling it for me (and therefore the user) and sending back a useful message, should I bother with Propel validation as well as my own security/courtesy validation ?
I cannot find any mention in the docs of what happens if you give Propel - for whatever reason - a value it doesn't anticipate for the field, or how to handle it.
I do hope this makes sense and that someone can point me at a method that will mean I only need to validate input in one place.
I've hacked together a rough ready solution that will allow me to:
Pre-validate a field against a CustomValidator without setting it in the new object
Retrieve the validator's message for return to the user
I take the form input, sanitise it of course, and then create an object:
$event = new Event();
With my user form in mind, I then pre-check the field I know will fatally fall over if the content's bad, and only set the field in my new object if it would validate:
if ($check = $event->flightCheckFail('StartingDate','DateValidator',$sanitisedFormVal))
echo $check;
else
$event->setStartingDate($sanitisedFormVal);
Method flightCheckFail() will return false if the data from the form would validate against the field, it returns the validator's error message if it would fail.
The method's added to my Event class as follows. Its arguments are the field name, the class of the CustomValidator (which simply runs an strtotime check), and the sanitised form value:
public function flightCheckFail($name,$validatorClass,$value) {
$colname = $this->getPeer()->getTableMap()->getColumnByPhpName($name)->getName();
$validators = $this->getPeer()->getTableMap()->getColumn($colname)->getValidators();
foreach($validators as $validatorMap)
if ($validatorMap->getClass() == $validatorClass) {
$validator = BasePeer::getValidator($validatorMap->getClass());
if ( $validator->isValid($validatorMap, $value) === false)
$failureMessage = $validatorMap->getMessage();
} // if $validatorMap->getClass() == $validatorClass
if($failureMessage)
return $failureMessage;
else
return false;
}
I should be able to use this to work around handling dates in forms, but I'll need to check what other types in Propel might require this sort of handling.
I can stop the form handling wherever this reports a validator error message and send it back. When the user enters valid data, Propel (and normal Propel Validation) gets to continue as normal.
If anyone can improve on this I'd love to see your results.
You could also use a MatchValidator, with a date RegExp, no need for extra functions

Resources