Laravel 4 Unique Validation Rules Not Working

piso picture piso · Oct 5, 2014 · Viewed 9.4k times · Source

need help updating a unique rule in my validation rules. I have a abstract validator that will validate a rules before storing into my database and in the rules array I set the email to be unique when creating or registering a user but when updating the user the enique email should not validate if the email is owned by the user.

abstract class Validator

abstract class Validator {

    protected $errors;

    protected $attributes;

    public function __construct($attributes = null)
    {
        $this->attributes = $attributes ?: \Input::all();
    }

    public function passes()
    {
        $validation = \Validator::make($this->attributes, $this->rules());

        if ($validation->passes()) return true;

        $this->errors = $validation->messages();

        return false;
    }

    public function getErrors()
    {
        return $this->errors;
    }
}

Validation Rules(UserRule.php)

use MyCustomValidatorNamespaceHere....

class UserRules extends Validator

public function rules()
{
    return [
        'email' => 'required|email|unique:users,email,id',
        ...
    ];
}

and in my UserController I injected the UserRule in the constractor. (UserRule $userRule). Here is the code in the update method.

public function update($id)
{
    $if ($this->userRule->passes())
    {
       $this->user->find($id)->update(Input::all());
       return .........
    }
}

But the validation always fail and displaying the error that the email is already taken. Please help guys.

Answer

Marcin Nabiałek picture Marcin Nabiałek · Oct 5, 2014

The problem is your rule. When you update, you need to use unique that doesn't check record you update. So you should have:

 unique:users,email,id

but for example:

 unique:users,email,10

if you edit record with id 10.

What you could do is to define this rule:

'email' => 'required|email|unique:users,email,{id}',

and your passes method:

public function passes($id = null)
{
    $rules = $this->rules();
    $rules['email'] = str_replace('{id}', $id, $rules['email']);

    $validation = \Validator::make($this->attributes, $rules);

    if ($validation->passes()) return true;

    $this->errors = $validation->messages();

    return false;
}

and now in update rule use:

if ($this->userRule->passes($id))

By the way you have error in $if ($this->userRule->passes()) - it should be if and not $if