validating icon indicating copy to clipboard operation
validating copied to clipboard

Validation incorrect work with accessors

Open EugeneG9 opened this issue 7 years ago • 4 comments

I have model with accessors, originaly I have integers in validated model properties, but when i accessing it, model returns me words represents that integers. Validating trait validating accessors result except of native values. I think - problem is on line ValidatingTrait:139: $attributes = $this->getModel()->getAttributes();

EugeneG9 avatar Jan 20 '17 15:01 EugeneG9

This is by design, at some point the decision was made that the validator should operate on the mutated values. Looking back I'm not sure if I still think that was the right move, but that's how it is for now. Could look into adding an option that lets you opt-in/out of mutated values.

dwightwatson avatar Jan 21 '17 07:01 dwightwatson

Hi,

I have same problem with throw a validation on password field in User model. I have a mutator for that field. This mutator function apply bcrypt function to my custom password and convert it in a string valid. I too would like can modify the validation on a custom and specific list fields.

Thanks for you work.

mpijierro avatar Aug 08 '17 11:08 mpijierro

I came to the same conclusion as @EugeneG9. The method should be:

    public function getModelAttributes()
    {
        return $this->getModel()->attributesToArray();
    }

The attributesToArray method already returns attributes that are mutated and converts Carbon dates to strings. Plus, it adds appended accessors, and applies type casting.

scottsteil avatar Oct 19 '17 21:10 scottsteil

Accessors especially pair really nicely with this validator class. Here's an example of a complex, model-specific validator rule. This ensures that the passed percentage fields all add to 100%.

use Illuminate\Database\Eloquent\Model;
use Watson\Validating\ValidatingTrait;

class SomeModel extends Model
{
    use ValidatingTrait;

    protected $fillable = [
        'percent1',
        'percent2', 
        'percent3', 
    ];

    // We validate the 'total' accessor even though it's not a fillable field
    protected $rules = [
        'percent1' => 'required|integer|between:0,100',
        'percent2' => 'required|integer|between:0,100',
        'percent3' => 'required|integer|between:0,100',

        // the percent fields must add to 100%
        'total' => 'required|integer|size:100',  
    ];

    public function getTotalAttribute()
    {
        return $this->percent1 + $this->percent2 + $this->percent3;
    }

    // The total attribute needs to be appended because it doesn't already exist
    // Otherwise, Laravel's toArray method doesn't include it for efficiency
    protected $appends = ['total'];
}

I can't think of another way to do this is other than with a separate validation in the controller before I would save the model. I prefer the model to handle validation of the data it represents. Also, I'd want that validation rule error to be grouped with any other failed rules.

I love that I can set the throwValidationExceptions flag and have the exception handler deal with error. It keeps everything sorted and clean.

scottsteil avatar Oct 19 '17 22:10 scottsteil