3
votes

We know laravel has an update() method that update records through "put" http method. Everything works cool except when I try validating the new input values against a static $rules method in my User model. Please have a look at my model

protected $guarded = ['id', 'admin'];

public static $rules = [
    'name' => 'required|min:4',
    'username' => 'required|min:3|alpha_num|unique:users',
    'email' => 'required|email|unique:users',
    'password' => 'required|alpha_num|between:5,12|confirmed',
    'password_confirmation' => 'required|alpha_num|between:5,12',
    'phone' => 'required|min:5|alpha_num',
    'city' => 'required|min:2|alpha',
    'town' => 'required|min:2|alpha_num',
    'address' => 'required|min:5|alpha_num',
    'blood' => 'required|min:2',
    'img' => 'image|mimes:jpeg,jpg,bmp,png,gif',

    'active' => 'integer',
    'admin' => 'integer'
];

You see I have made email as unique to the user table. So, when I try to update the records, which are about the logged in user's profile information, if I update all the records along with the email address it works. But if I leave the email field as is, it throws the validation error saying the email address is already taken. But I want laravel to validate only the updated fields so that users can update whatever they want or leave one or two as before. Is there any way to accomplish that?

Please now check out the controller method that is responsible for updating the newly inputted data

//update the changes now
public function update($id) {

    $user = User::find($id);

    $validator = Validator::make(Input::all(), User::$rules);

    $input = array_except(Input::all(), ['_method', 'password_confirmation']); 

    if( $validator->passes() ) {
        $user->save($input);

        return Redirect::to('donors/'.$user->username.'/profile')
            ->withMessage('Information Updated');           
    } 

    return Redirect::to('donors/'.$user->username.'/profile/edit')
        ->withMessage('Something went wrong! Please fix the errors.')
        ->withErrors($validator)
        ->withInput();  
}

For understanding the scenario more clearly, I am adding the form from view and the route file snippet too.

Route

Route::put('donors/{id}', ['uses'=>'DonorsController@update']);

Views form

            {{ Form::open(['url'=>'donors/'.$donor->id, 'method'=>'put', 'role'=>'form']) }}

            <table class="table table-bordered donors-table">
              <colgroup>
                <col class="col-xs-1">
                <col class="col-xs-7">
              </colgroup>
              <thead>
                <tr>
                  <th>Type</th>
                  <th>Description</th>
                </tr>
              </thead>
              <tbody>
                <tr class="odd">
                  <td>
                    <span class="text-green">Name</span>
                  </td>
                  <td>
                    {{ Form::text('name', $donor->name) }}
                    <span class="text-red input-error">{{ $errors->first('name') }}</span>   
                  </td>
                </tr>
                <tr>
                <tr>
                  <td>
                    <span class="text-green">Email</span>
                  </td>
                  <td>
                    {{ Form::email('email', $donor->email) }}

                    <span class="text-red input-error">{{ $errors->first('email') }}</span> 
                  </td>
                </tr>

                <tr class="odd">
                  <td>
                    <span class="text-green">New Password</span>
                  </td>
                  <td>
                    {{ Form::password('password', null) }}

                    <span class="text-red input-error">{{ $errors->first('password') }}</span> 
                  </td>
                </tr>
                <tr class="odd">
                  <td>
                    <span class="text-green">Confirm New Password</span>
                  </td>
                  <td>
                    {{ Form::password('password_confirmation', null) }}
                    <span class="text-red input-error">{{ $errors->first('password_confirmation') }}</span> 
                  </td>
                </tr>

                 <tr class="odd">
                  <td>
                    <span class="text-green">Blood Group</span>
                  </td>
                  <td>
                    {{ Form::text('blood', $donor->blood) }}
                    <span class="text-red input-error">{{ $errors->first('blood') }}</span>   
                  </td>
                </tr>
                <tr>
                <tr class="odd">
                  <td>
                    <span class="text-green">Address</span>
                  </td>
                  <td>
                    {{ Form::text('address', $donor->address) }}
                    <span class="text-red input-error">{{ $errors->first('address') }}</span> 
                  </td>
                </tr>

                <tr class="odd">
                  <td>
                    <span class="text-green">City</span>
                  </td>
                  <td>
                    {{ Form::text('city', $donor->city) }}
                    <span class="text-red input-error">{{ $errors->first('city') }}</span> 
                  </td>
                </tr>
                <tr class="odd">
                  <td>
                    <span class="text-green">Town</span>
                  </td>
                  <td>
                    {{ Form::text('town', $donor->town) }}
                    <span class="text-red input-error">{{ $errors->first('town') }}</span> 
                  </td>
                </tr>

                 <tr class="odd">
                  <td>
                    <span class="text-green">Phone</span>
                  </td>
                  <td>
                    {{ Form::text('phone', $donor->phone) }}
                    <span class="text-red input-error">{{ $errors->first('phone') }}</span>   
                  </td>
                </tr>
                <tr>
              </tbody>
            </table>
                <p class="submit clearfix">
                     {{ Form::submit('Update', ['class'=>'btn btn-success pull-left']) }}
                     {{ link_to('donors/'.$donor->username.'/profile', 'Cancel', ['class'=>'pull-right btn btn-danger']) }}
                </p>
            {{ Form::close() }}

Did I miss anything please? Let me know if I should show any other snippet of my codes.

2

2 Answers

4
votes

For updating you need to change the email rule ever so slightly. If as part of the Unique rule you pass the field to check and then a value it won't complain that the value is already taken.

In your case update your controller by placing the following just before you do the validation:

User::$rules['email'] = 'required|email|unique:users,email,' . Input::get['email'];

Your validation should now pass as you have told laravel that the email should be unique but that you will accept the current email address.

1
votes

Either do

$user->update($input);

or

// this is exactly what `update()` method does.
$user->fill($input)->save();

And adjust validation rules as well

'email' => 'unique:users,email_address,10'

where 10 is ID of current model instance. To achieve this, you need to parse rules in some way.