4
votes

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.

5
I solved this problem here on stackoverflow in a generic way. It will automatically adapt your rules if you do an update and add exceptions to your :unique if necessary.cgross

5 Answers

4
votes

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

1
votes

You can use the route method inside your request class to except an id from the validation

public function rules()
{
    return [
        'email' => 'required|email|unique:users,email,'.$this->route('user'),
        ...
    ];
}
0
votes

I had a problem like that before and it was difficult to find an answer. Here is what I did.

class UserRules extends Validator {

public function __construct($input = NULL) {
    $this->input = $input ?: \Input::all();
    if(isset($this->input['id'])):
        self::$rules['username'] = 'required|unique:users,username,'.$this->input['id'];
        self::$rules['email'] = 'required|email|unique:users,email,'.$this->input['id'];
    else:
        self::$rules['username'] = 'required|unique:users';
        self::$rules['email'] = 'required|email|unique:users';
    endif;
}

public static $rules = array(
    'company_id' => 'required',
    'role' => 'required',
    'password' => 'sometimes|required|confirmed'
);

}

You need to use self:: because $rules is static.

0
votes

I have moved this function:

public function passes($id)
{

    $rules = static::$rules;

    $rules['username'] = str_replace('{id}', $id, $rules['username']);
    $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;

}

into UserRule.php and commented the same function in abstract class Validator Now updating is working.

-1
votes

I solved this problem here on stackoverflow in a generic way. It will automatically adapt your rules if you do an update and add exceptions to your :unique if necessary.