Use Validation in FormType or in Entity / Yaml - validation

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 ?

Related

UniqueEntity on multiple fields doesn't show an error message

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.

Apply several constraints in one "validate" pass in Silex

I'm using Silex, and trying to validate some value with validator service. But the problem is that I need apply several constraints to one value, but validator don't let to do this without using Required constraint.
When I just want to validate a choice value (say, 'apple' or 'orange') I have to wrap constraints Choice and NotNull (because Choice allows a null value) into Required and Collection (because Required cannot be used without Collection and it is CollectionValidator who validates series of Required's constraints) like this:
$violations = $app['validator']->validate(array('value'),
new Collection(array(
new Required(array(
new Choice(array('apple', 'orange')),
new NotNull()
))
)));
It looks verbose so I'm looking for more elegant solution (for such explicit use of validator).
You can use the validateValue function that accepts an array of constraints as second parameter.
$violations = $app['validator']->validateValue('value', array(
new Choice(array('apple', 'orange')),
new NotBlank()
));

Set values on Symfony2 validation with no form

I'm coding an API and I'm doing the create method. I'm doing the following without needing a form:
$params = array('title' => 'test', 'parent_id' => 781);
// bind data
$place = new Place();
$place->bind($params);
// validate params
$errors = $this->validator->validate($place);
I need to check that parent_id is a correct value (its object exist - i know how to do this) and after that, I need to set some values dependent on the parent. So at the end the Place object will have the fields: title, parent_id, level, country_id for example.
How would you do this? On the validation? How? If not, how to avoid calling two times the DB to get the parent object?
You should first validate & then set any additional values afterward. Anything that modifies the value does not belong in the validator.
If your using doctrine, it should load the parent object into memory when you first access it, so it won't need to actually query the database again when you access the parent object a second time.

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

Cake PHP automagic forms and multiple tables

I have a form with the following fields:
firstName
lastName
emailAddress
followed by (up to) ten name/email fields, like so
friendName-1
friendEmail-1
friendName-2
friendEmail-2
...
etc.
The firstName, lastName & emailAddress fields will be saved into a 'referrals' table, but 10 name/email pairs will go into a 'friends' table, containing a foreign key refferal_id.
Normally I use the cakephp 'automagic' forms, and set up my validation in the model, and do a $this->model->save(); If it fails I fall back on my model validation rules and the error messages get spat back into my form html. No problems.
How would I do this for TWO tables though? I'm thinking that the automagic stuff is not the way to go, but I feel I will lose a lot without it, such as validation in my models and custom error messages.
Is there a happy medium? I'm fairly new to cake so I'm wondering if theres a way to use automagic with multiple tables.
See http://book.cakephp.org/view/84/Saving-Related-Model-Data-hasOne-hasMany-belongsTo
Create the relationship in your Referral model:
var $hasMany = array('Friend');
Essentially, make sure you name your fields correctly, e.g.
echo $form->create('Referral');
echo $form->input('first_name');
echo $form->input('last_name');
echo $form->input('email');
foreach (range(0,9) as $index) {
echo $form->input('Friend.'.$index.'.name');
echo $form->input('Friend.'.$index.'.email');
}
echo $form->end();
And in your referrals controller:
function add() {
if(!empty($this->data)) {
$this->Referral->saveAll($this->data, array('validate'=>'first'));
}
}
First, I really hope that you don't have 20 fields in table called 'friendName-1', 'friendEmail-1', etc. Your second table should have 3 fields--your referral_id, friendname, and friendemail. If you don't want to normalize, then you don't need the second table.
But I digress, the way to keep your automagic forms is to put a "hasMany" in your referrals model and/or a "belongsTo" in your "friends" model. Then you can still use the FormHelper and Model->Save().

Resources