A very interesting subject has arisen today with two points of view.
Using Doctrine Entities
Should the validation of the data be done at the point when a setter method is called? I.e. Inside a setFieldName() method, or
Should the entity be validated as a whole for valid data when an event is triggered on an entity?
Is there a normal or tried and tested theory and/or point of view on this?
I don't think there is a "normal"/standard way to go about this - I guess it depends on your needs. I can tell you my point of view:
For me data validation should be done on setters - that is - as soon as possible. This way you cannot have an entity with invalid data set on it and it will save you headaches when you are going to persist.
Try to think of it this way: Let's say you have a car that runs on petrol. You go to the gas station to refill. You have two pumps: petrol and gasoline. Without validation, you would be able to put either type of fuel in there and until you turn the engine on nothing would happen. But when you do, if you put the wrong type of fuel, it would be too late. Boooooooom! Of course entities don't explode.;)
Having said that, sometimes it is not possible to do validation on a single setter because it could be dependent on another property(which has not been yet set). Something like VATID for user entity where property user_type(private|company) has to be available in order to be able to check and force VATID for companies. In this case you'd do some PrePersist/PreUpdate validation.
Related
The Symfony 2 Form Component really is something. I guess you know that. Trying to understand what works how is just an seemingly impossible task; and I'm quite experienced at browsing through codebases.. But man, the Form component.. OMG
TL;DR
Below are details, this issue tries to ask
Is it possible to replace the class \Symfony\Component\Form\Form?
Or: How to easily get all extra data from all fields of type form of a form?
Or, a related question: How on earth does it work that if i do $form->add('ss', 'form') - obviously the Core\FormType class gets involved but when i retrieve it later, it is an instance of \Symfony\Component\Form\Form? Where does that happen and can this maybe overriden so it uses a different class there?
Details
The situation
Imagine a Controller that receives a n deep JSON payload. This payload gets decoded and validated through Form. Now, most of this JSON structure is mapped by Models (Doctrine ODM Entities). But some sub-properties are just "hashes" - the client is allowed to post whatever he wants there.
Those "hash" subproperties are fields of type form, are compound flagged and can have extra fields.
The problem
Bottom line our problem is, that all "extra fields" are not returned by $form->getData(). We are unable to specify those fields (and their types) as we don't know what will come - so all this data is part of extraData.
The solution?
So i thought - OK - let's modify the FormFactory so it'll return our Custom extension of Form - one that also returns extraData when getData is called. Easy right.? Noo, not easy..
My idea let me inspect FormFactory, the FormBuilders, the ResolvedFormTypes, whatnot.. and at all important places (like formBuilder->getForm()) - the classes I want to override/replace are instanciated static - no usage of the DIC..(!)
I've read somewhere that the Form component in Symfony 2 was written by the devil himself to let we developer go mad. Luckily I'm not so mad to try to replace the entire Form component by myself ;)
Jokes aside, when you define a form (by creating a <entity>Type class, like UserType) you are defining a new type that can be as simple as a single text input or as complex as full-fledged form (our UserType from before). The "real" form (Symfony\Component\Form\Form) is created from your type definition:
return $this->container->get('form.factory')->create(
new UserType(), new User(), $options
);
Have you evaluated the idea to create a custom form type for your "extraData"? Or maybe it can be mapped as a JSON string that's created by a client-side JavaScript before submit.
one "simple" question: http://mwop.net/blog/2012-07-02-zf2-beta5-forms.html
is it possible to use the zf2 zend form annotation validation rules without using zend form, so i can share the validation rules between a model validator (e.g. using for check if the model is correct before persisting it) and the zend form validation?
if my "name" should be not empty and between 5 and 20 characters, it is the same rule for the form and the model.
i hope i pointed it out clearly
Roman
Well, since all data that the models are getting would be from user input or the database, you shouldn't need to test the models itself, too. THe data inside the database should be correct!
IE: trust your own data but not the users?
But if you still wanna do that, i guess you could build the form with the AnnotationBuilder, then get the InputFilters from the Form (im sure there's a method, maybe on per-element-basis) and then use those inside your models - but as my first paragraph implies, i see this as a quite useless point :)
As for multi usable input filters, best thing would be to write own classes extending Zend\InputFilter\InputFilter on a per model basis. When you build your form then you can attach that class as the filter definition via $form->setInputFilter($myModelInputFilterClass) and you could also call that class inside your models to run your data through those filters. I haven't done this manually but it should work.
The only pitfall i guess might happen if you run into required statements. Checking on a per element basis, i don't know if that will work, too. As the InputFilter checks against all given filters. Though if you import a full CSV-Sheet or something you'd have a populateFromCsv() function or something that then checks all data anyways i guess.
An Entity (let's say a UserEntity) has rigid rules for it's properties, and it can exist in 2 states - persisted (which means it has an id) and pre-persisted (which means it does not have an id yet).
According to the answer to this question about how to handle required properties, a "real" UserEntity should only ever be created with an id passed in to its constructor.
However, when I need to create a new UserEntity from information sent by the browser, I need to be able to validate the information before persisting into the db.
In the past, I would simply create a blank UserEntity (without an id), set the new properties, and the validate it - but, in this new, more secure way of thinking about Entities, I shouldn't ever create a new UserEntity without its id.
I don't want to create TWO places that know how to validate my UserEntity's properties, because if they ever change (and they will) it would be double the code to update and double the chances for bugs.
How do I efficiently centralize the validation knowledge of my entity's properties?
Note
One idea I had is reflected in this question, in which I consider storing the non-state properties like email, password and name in a standardized value object that would know about the rules for its properties that different services, like the Controller, Validator, and Repo, or Mapper could use.
that's what factories are for. to the factory method you pass only the data that is required to enforce the real invariants of UserEntity (take some time to figure out what are your real invariants of UserEntity and you'd better do it with your domain experts).
in the factory method you create a new Id and pass it to the UserEntity constructor.
In this stage i don't think it is that bad to discard the instance if the validation inside the constructor fails. in the worst case - you've lost an id... it's not a case that suppose to happen quite often - most of the time the data should be validated in the client.
Of course another option is that in the factory method you first validate the parameters and only then create a new Id and pass it to the UserEntity constructor.
itzik saban
I think you have a couple of options to consider:
(1) Consider your first comment:
An Entity (let's say a UserEntity) has rigid rules for it's
properties, and it can exist in 2 states - persisted (which means it
has an id) and pre-persisted (which means it does not have an id yet).
Here, you are already mention that validation actually depends on whether the entity has been persisted. In other words, if the entity hasn't been persisted, then it should be valid without the ID. If you continue with this domain specification, I feel the validation should act accordingly (e.g. return isValid even without an ID if the object hasn't been persisted)
(2) If you assume "valid" means the object has an ID, then you would need to generate the ID upon creation. Depending on how your IDs are generated, this could get tricky (e.g. save to database and return created ID, or generate unique identifiers somehow, or ...)
Using either approach, its probably worth implementing common base class(es) for your Entity (e.g. with ID) to help minimize duplicating validation across the different states. Hopefully, this shields the derived entities from the common validation as well.
In my opinion , save() , and load() methods should be doing both validation and setting ID attribute . And by the way an entity without Identity attribute is not a entity at all .
In my view Identity attribute should be validated and ensured when entity is in transit e.g
loading from db , loading from file or (after) saving to db such that
if loading from db fails discard the entity saving to db/file fails discard the entity .
Since validation is business log /behavior etc and a better pattern for that would be
Strategy Pattern (http://en.wikipedia.org/wiki/Strategy_pattern)
The topic of how to do validation correctly is somewhat of a grey area.
Validation is typically cast as Invariant and Contextual validation. Invariant validation pertains to those things that, according to your problem domain, have to be present in order for your model to function properly in its intended role. Contextual validation pertains to state that's valid within a given usage context (e.g. A Contact used for emailing needs an email address, but doesn't need phone number; a Contact used for catalog mailings needs a mailing address, but doesn't need an email, etc.).
If you want to be architecturally pure, then technically the concerns of input validation (what your customers are typing into a user interface) and the state of a given entity are two different concerns. Ideally, your domain should have no knowledge of the particular type of application it's written for and therefore shouldn't be burdened with providing error messages suitable for use, either directly or indirectly, in displaying error messages back to the user. This presents a bit of an issue, since it can lead to duplicate or triplicate error checking (client side, service side, domain-level), so many opt for a more pragmatic approach of dealing with most validation external to the entity (e.g. validating an input model prior to entity creation).
I don't see the problem with persisting invalid data. What is valid or not is a business concern and can sometimes depends on the situation. The database doesn't care about these business rules.
If I have to fill out a big form online and the very last step requires me to enter my credit card information and I don't have my card ready, I'll have to discard all that information and the next time enter it all over again (which won't happen because I rather go somewhere else). I would like that application to store the information I already gave and later on I can make it functionally valid. As long as it isn't valid, I can't order things online.
There have been a couple of discussions regarding the location of user input validation:
Should validation be done in Form objects, or the model?
Where do you do your validation? model, controller or view
These discussions were quite old, so I wanted to ask the question again to see if anyone had any fresh input. If not, I apologise in advance.
If you come from the Validation in the Model camp - does Model mean OOP representation of data (i.e. Active Record/Data Mapper) as "Entity" (to borrow the DDD terminology) - in which case you would, I assume, want all Model classes to inherit common validation constraints. Or can these rules simply be part of a Service in the Model - i.e. a Validation service? For example, could you consider Zend_Form and it's validation classes part of the Model? The concept of a Domain Model does not appear to be limited to Entities, and so validation may not necessarily need to be confined to this Entities.
It seems that you would require a lot of potentially superfluous handing of values and responses back and forth between forms and "Entities" - and in some instances you may not persist the data recieved from user input, or recieve it from user input at all.
I much prefer to put validation in the model, personally. Security considerations of course are beyond the scope of what a model should be used for, but nothing says that a model is updated in exactly one place by exactly one form. By putting type validation and sanity checking outside the model, you have to validate every time you set anything on it, which leads to copy/pasted code that's difficult to update.
I use Zend_Form as part of my models - models are creating the Zend_Form objects. I go this way because Zend_Form is not about the form rendering only; backed up with Zend_Validate and Zend_Filter it is a very powerful tool (my fav from the ZF stack). Matthew Weier O'Phinney wrote a nice post about using Zend_Forms in models: http://weierophinney.net/matthew/archives/200-Using-Zend_Form-in-Your-Models.html
Data validation should be on its own, called by the controller just before committing to the model.
Haven't used PHP and haven't worked with Zend framework (have heard though), but I really like Jimmy`s blog post about validation from domain driven design perspective.
I considered many different approaches of data validation, and decided that best way of validation - it's validation before entity creation, since validation it's something which can be very dependent from context, and entity itself should not perform validation, because entity should always be in valid state.
So maybe best approach - use separate validation classes to validate data before passing it to entity constructor.
When handling user input, you should definitely handle all logic-oriented validation outside the model.
The model doesn't care about your business logic. The model doesn't care if your start date is after your end date - all the model cares about is that the date is a valid entry for that particular field in the database. It checks the data, sees a properly formatted date and moves on to the next one, because the model's entire realm of responsibility is to ensure the smooth flow of data to and from a data source.
Classes like Zend_Form are nothing more than abstractions of your view.
This is a quick question relating to Symfony, but could be a general MVC question.
I have a class in my model, for example, WebUser. This class has a property of email_address. This value must be unique to each WebUser.
Now, I've made it so all my Symfony forms validate that the email_address is unique for the given WebUser, however I'm wondering if I should add this validation to the model as well?
But this also got me thinking, should you actually validate every set() method in the model? It seems a wise enough decision to make sure no erroneous data ends up in the database, however most (if not all) data has to go through the controllers, which validate as well. So to me it seems I'm running the same validation twice and it just seems pointless?
What are your thoughts on this? I'm still leaning towards validation in the model as that makes the most sense as it dictates the business logic.
If you should validate in the model, how do you throw an appropriate set() error in Symfony that is handled correctly by the form framework?
Thanks.
I disagree with "Validation should be part of domain logic, not front-end logic".
Validation is a complex functional part of your application and must be context aware. ie. you have to know is the user is logged in, what kind of credentials she has, the status of the request/form and so on. Models instead must be context agnostic (to work in any environment not only http request but also cli etc.) so they don't know about the user, the state and the http request. This is a strong requirement for the testability of your model classes.
For the summentioned reason functional validation must belong to the form which knows the application state (ie. session). symfony helps a lot with the sfValidator* classes which belongs to the form component indeed. That's the reason why forms are tested with functional testing.
Data validation should be in the model instead (ie. check if the value is an integer or a string, check if it's null and so on). This is easily accomplished with the Doctrine in-schema validation rules.
I can't speak specifically to Symfony, but I know that I purposely shun Zend Framework's form validation, and instead validate on my models (Zend Framework does not provide its own Model component, so it has no actual opinion on the matter).
There's nothing wrong with validating on the form, but I think you should also be validating on the model. Validating on the form might be useful for quick and easy input checking, especially if the processing logic is complex - you won't waste time working with data that's obviously bad.
Reasons I think model validation is best:
There's a chance a model will alter the data after it passes through the form and before it goes into the DB
Validation should be part of domain logic, not front-end logic (I realize Symfony seems to disagree).
Validation state travels with the model object, instead of the form object.
If you're not totally sold validating only in the model, a combination of the two sounds like a good solution.
EDIT: At the end of the day, it might make the most sense to just go with your framework on this. If Symfony seems most opinionated toward validation in the controller, and doesn't provide an easy path for validation in the model, just go with what they want you to do (or the direction in which the Symfony community leans). Fighting your framework is never fun.
I can't help out with the symfony part but most MVC-Frameworks do validation in the model, since this is the only place inside a MVC environment where validation should be.
This goes for the validation of the model's attributes of course.
I Think You Should User MVC Validator Tool Ket Insted of using others rely on modelstate its easyer and also testable and its based on formcollected not to the model that give you free run way
Regards MArwan HAfez