Request validation imposes validation code duplication in Symfony - php

Say I have a REST API method creating a user. I also have a user entity with configured validation constraints. The question is how to validate the data from the request. My problems are:
I can't populate a user instance without validating the data in the request beforehand - some data might be missing in it, other might be invalid. For example null passed to a user entity's setter with string type-hinting.
I'm not so keen to validate the request data separately, before populating a user instance, because it would be a duplication of the validation constraints configured for the user entity. It would be a problem to manage the same or similar validation constrains in two places - the controller and the entity validation config.
So basically I want to avoid the duplication of the validation constraints in the code and the config, but at the same time I'm forced to duplicate it before populating the entity. How can I get over this?

It is quite physiologic.
What I would suggest is to use a DTO where no restrictions are checked (basically where you can accept "all kind of data" in your setters or even by having public properties that is less cumbersome) and to have a validation on it.
When the DTO is valid, create the underlying object in a valid state (Value Object?)
Of course you need to "duplicate" some constraints but I would not consider this as a real duplication because, actually, DTO and underlying object are not the same object even if them seems to be related. If you disagree - and it could be the case - just stop and think about the boost you'll have by decoupling entity (that should be always in a valid state) from the model where user input data are taken.

Related

Validation layer in PHP and DB interaction

In input of my application I have the following data: airplane_id, airport_id and passenger(s) details.
I need to make sure that selected airplane_id could reach airport_id. It might be done only with help a SQL query, but this checking is still a validation process, isn't it?
Validation should happen before I will save passenger(s) details.
In my application model, it is the ActiveRecord pattern object which represent a table. I would rather make Validator as a separated layer than to build it into the Model layer. But in this case I have an extra issue: usually Validators are general (their rules might be applied to any set of data). For instance is this data email? or IP? or date? etc.... but never mind what the data is.
In my case, the mentioned rule won't be common at all; it will definitely be a specific rule, which can't be used by any other input data. So my question is: Is this checking still part of the validation process?
And if yes, will Validator violate the S principle from the set of SOLID?
It is validation and you should use a separate validation layer (single responsibility for input validation). Input validation isn't just data type checking, it can be much more complex. Model validation might still be needed though.
Think of input validation as whitelist validation (“accept known good”) and model validation as blacklist validation (“reject known bad”). Whitelist validation is more secure while blacklist validation prevents your model layer from being overly constrained to very specific use cases.
Invalid model data should always cause an exception to be thrown (otherwise the application can continue running without noticing the mistake) while invalid input values coming from external sources are not unexpected, but rather common (unless you got users that never make mistakes).
See also: https://lastzero.net/2015/11/form-validation-vs-model-validation/
Yes, these checks are validation.
Speaking from experience with a MVC pattern framework(Yii/2), I would say that you could make an abstract validator class and from there extend it into your concrete validators and call those validators from the model class. This will need a Model->validate() call, but having separate classes that actually check the data will not violate the S in SOLID, while Model->validate() will just loop through the validatos validate methods and store the error messages in an array.

Doctrine Entity Validation (Setter Method Validation or Event Driven)

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.

Does input filter / validation code belong in the controller or the domain model?

I have been using php for awhile but am new to OO php. As an exercise for myself I am building a small MVC framework.
I realize there is probably not a definitive answer for this, but I am wondering: Where does the input filter / validation code belong?
Should it be a part of the controller, where the request is parsed?
Or is it more appropriate to have filter / validation code in the domain model, so that each domain object is responsible for validating its own info.
Any advice would be much appreciated.
Controller is not responsible for validation in any way, shape or form. Controller is the part in presentation layer which is responsible for reacting on users input. Not questioning it.
The validation is mostly the responsibility of domain objects, which are where most of domain business logic ends up within the model layer. Some validation is what one would call "data integrity checks" (like making sure that username is unique). Those constraints are enforced by DB structure (like with UNIQUE constraint in given example or NOT NULL in some others). When you are saving the domain object, using data mapper (or some other storage pattern), it might raise some exceptions. Those exceptions too then might be used to set an error state on a particular domain object.
If you have a form, it will be tied to one or more domain objects, which, when the form is posted, validates it. The current view then requests information from the model layer and, if there has been an error state set, displays the appropriate warnings.
Controllers would typically handle request data (GET / POST) and detect invalid form submissions, CSRF, missing fields, etc. for which the model should not be concerned about. This is the most likely place where you would write the bulk of mostly your filtering code; validation should only go as far as sanity checks for early failure (e.g. don't bother to send an email address to the model if it's not a valid email address).
Your domain objects may also provide validation hooks (even filtering), which would reduce the controller's responsibility, but in most cases I personally find it easier to work with a contract based model (the model assumes you're passing legit values) because it's easier to directly translate validation issues to specific form fields.
The model itself may do validation as well, albeit different from aforementioned input filtering (and content type validation); for instance, it might check whether an email exists in the database rather than making sure it's a valid email address.

How to handle Domain Entity validation before it's persisted?

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.

Define "Validation in the Model"

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.

Categories