I have a question because I don’t want to do something wrong.
I have a polymorphic relation called votes. Well, I want to save votes but I need to validate if a user already has voted. But even if, in some cases a user can vote multiple times. It depends on the type (as said, polymorphic relation). I’ve set this data in a config file.
Now, where should I validate the votes? I thought I could do it in the model with a static method but then I’d be retrieving the config files in the model and also I’d have to return multiple errors. Something like “you have already voted” or “you can vote again in 1 hour”.
I’d do that with some kind of error codes which I’d pass to the controller and then to the view to inform the user. But it seems wrong to me.
What would be the right way of doing this?
12
I think you should validate your models in… model validators 😉
In my current architecture each model has an associated validator class, which contains validation logic. (Controllers have validators as well, but that’s not the point). This is because validation logic can sometimes be complex enough, especially when models receive states.
To validate a model I just pass the result of $model->getAttributes() to a validator. The part, responsible for creating a validator and passing it attributes is now a part of my custom BaseModel class.
I’ve set it up so validation runs when model is saved. If model is invalid, exception is occured. So, the controller or service, saving the model, are responsible for it’s validation.
Validation result is empty when validation succeeds or a hash of errors (‘fieldName1’ => ErrorsArray1). ErrorsArray is a standard Laravel’s MessageBag, using which it’s easy to render errors to user.
So, to model/controller it doesn’t matter if User can’t vote at all, or will be able to vote again in 1 hour. Model validator creates an error message (cannot_vote or cannot_vote_tmp) and just bubbles it to controller, which passes it to view. View translates message if needed and presents it to the user.
Currently errors are just enumerated and presented to user using a simple list next to the input field it is related to. But this logic can be extended. If it becomes complex enough, you can place some of it into a ViewComposer, which will take errors from controller, calculate some state from them and then pass this state into a View freeing it from complex calculations.