Laravel-Model-Validation icon indicating copy to clipboard operation
Laravel-Model-Validation copied to clipboard

Trying to understand how to update

Open andyjessop opened this issue 10 years ago • 3 comments

With this method, let's say you fill a update some fields on an entry, then call the save() method, the validation will run on all the fields currently set on the entry. But if the validation requires a field, say the email address, to be unique, the validation will fail because it already exists:

User.php:

protected static $rules = [
    'email' => 'required|email|unique:users',
    'firstname' => 'required',
    'lastname' => 'required'
];

Controller.php:

     // Get user from id
    $user = User::find($id);

    // Update user
    $user->update($data);

    // Validation when model is saved, via Way\Database\Model
    if ($user->save())
    {
            return Response::json([
                'data' => $user->toArray()
            ], 200);
    }

    if ($user->hasErrors())
    {
        return Response::json([
            'errors' => $user->getErrors()
        ]);
    }

Will return errors because the email address failed the validation. So, with this method, how do you tell the validator to ignore the unique rule for the email?

andyjessop avatar Nov 06 '14 10:11 andyjessop

There is a third field option on the unique validator that lets you specify an id to ignore in the validation check. So you can do something like:

$protected static $rules = array( 'email' => 'required|unique:users,email,{{$id}}');

tomwalsh avatar Feb 03 '15 03:02 tomwalsh

Adding {{$id}} to my ruleset doesn't seem to work. I've overridden the model to achieve this within a BaseModel class.

/**
 * Pre-process the rules by replacing instances of {{$id}} with the model id
 *
 * @return bool
 */
public function validate()
{
    foreach(static::$rules as $field => $rules) {
        $rules = explode('|', $rules);

        foreach($rules as &$rule) {
            $rule = explode(':', $rule);

            if($rule[0] == 'unique') {
                $rule[1] = str_replace('{{$id}}', $this->id, $rule[1]);
            }

            $rule = implode(':', $rule);
        }

        static::$rules[$field] = implode($rules, '|');
    }

    return parent::validate();
}

steadweb avatar May 10 '15 12:05 steadweb

I think what @tomwalsh wanted to say was that you have to append the id of the user to update. But to alter the rules you will have to copy the Laravel-Model-Validation Model file to your models folder and create a method to modify the static $rules array.

// in Models/Model.php
static function setRules($key = '', $value = '')
    {
        if(array_key_exists($key, static::$rules))
            static::$rules[$key] = $value;

        return static::$rules;
    }

Now in your update method (in your controller file) you'll have to alter the $rules array before it is used to validate the data:

// In Controllers/SomeController.php
public function update($accountId)
    {   
        Account::setRules('email', 'email|required|unique:accounts,email,'.$accountId);
        // Your logic here
    }      

That's it. You can now adapt your rules to any situation. I'll probably be pushing new changes to this repository sometime soon, I will include this proposal.

Also, check out Laravel Validation Docs (unique rule)

manuelro avatar May 20 '15 08:05 manuelro