Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

dcaldessa's avatar

Validation on update with unique ID

I am working on a project but am stuck at the moment on validation using a request file.

I am trying to pass the unique attribute of email on update of a user. If the user does not change his/her email but say changes their password I want to be able to update the record with out it throwing a unique id error or stating that the record already exists.

I have tried using the Rule solution in the laravel documentation but I get an error stating Class 'Composer\DependencyResolver\Rule' not found, we have determined that the unique method does not exist for rule. Not sure how I am supposed to get around this error thus I cannot use the Rule:: methods as stated in the documentation.

I have found some other solutions on this site but none of them seem to work. So making a post to see if I can get some insight on what to do next ..

My UserValidationUpdate request looks like this

'''php public function rules() { $user = User::find($this->user);

    return [

            'email' => 'required|email|unique:users,id,'.$user->id,

    ];

'''

and the update method on my AdminUserController is formatted like this

'''php

public function store(UserValidationStore $request) { $user = new User; $checkboxes = $request->input('group');

        $user->firstName = $request->firstName;
        $user->lastName = $request->lastName;
        $user->login_name = $request->login_name;
        $user->password = Hash::make($request->password);
        $user->email = $request->email;
        $user->group_id = serialize($checkboxes);
        $user->sendEmails = Input::get('sendEmail');
        $user->blockUser = Input::get('blockUser');
        $user->reqPasswordReset = Input::get('reqPasswordReset');
        $user->timezone = $request->timezone;
        $user->save();

    Session::flash('success', 'User successfully saved.');

    $groups = UserGroup::all();

    if ($request->get('submit') == 'saveAndClose'){
        return view('admin.user.index');
    }elseif ($request->get('submit') == 'saveAndNew'){
        return view('admin.user.create',compact('user','groups'));
    }
    return view('admin.user.edit',compact('user','checkboxes','groups'));
}

'''

By all accounts it looks to be setup correctly based on the suggestions that I have read in other posts. But when I go to test it by removing the data in the email input and hit save I just get a blank page with the correct uri in the address bar i.e admin/user/32 not sure why it is blank just again looking for some suggestions in figuring this out ..

thanks

dcaldessa.

0 likes
12 replies
Nash's avatar

You are probably looking for something like:

use Illuminate\Validation\Rule;

...

return [
    'email' => [
        'required',
        Rule::unique('users')->ignore($this->user->id),
    ],
];

This will ignore the unique rule when you update the user without changing the email.

See "Forcing A Unique Rule To Ignore A Given ID" under https://laravel.com/docs/5.4/validation

Edit: updated $user->id to $this->user->id

1 like
Snapey's avatar

(btw use backtick ``` around your code blocks not ' )

1 like
Snapey's avatar

Your original code would probably worked if you accessed the current user correctly (and this assumes that it is only ever the logged in user changing their details)

instead of

  $user = User::find($this->user)

This uses the user() function on the request class and also saves another DB fetch

$user= $this->user();

but you could use this directly in the rule;

    return [

            'email' => 'required|email|unique:users,id,'.$this->user()->id,

    ];

and not bother with grabbing the user.

or in the example from @Nash (v5.3 onwards)

return [
    'email' => [
        'required',
        Rule::unique('users')->ignore($this->user()->id),
    ],
];

dcaldessa's avatar

So i have tried the above solutions that have been provided ..

   return [

            'email' => 'required|email|unique:users,id,'.$this->user()->id,

    ];

returns an error

ErrorException in UserValidationUpdate.php line 41: Trying to get property of non-object

Also tried it with the rule syntax and still get the same error

I did try using this


$user = User::find($this->user);

 'email' => [
                'required',
                Rule::unique('users')->ignore($user->id),

and it throws no errors and just returns me to the index page as if i were clicking the save and close button.

dcaldessa's avatar

Also something else i have noticed is

$this->user() 

returns null on a dd

but when i use

$this->user

it returns the Id of the user when dd.

So is there something set wrong somewhere else in my application ?

Nash's avatar

@dcaldessa Yes, the example wasn't exact. I have updated $user to $this->user for future reference.

...and it throws no errors and just returns me to the index page as if i were clicking the save and close button.

It shouldn't throw an error as long as the user has the same email address. Wasn't this the point? It means that the validation succeeded.

Snapey's avatar

can you show your complete return UserValidationStore class ?

dcaldessa's avatar

ok this is my UserValidationStore class which is working correctly.

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class UserValidationStore extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return[
            'firstName' => 'required',
            'lastName' => 'required',
            'login_name' => 'required|unique:users,login_name',
            'password' => 'required|min:8',
            'confirm-password' => 'required|min:8|same:password',
            'email' => 'required|email|unique:users,email'
        ];
    }
}

The issue is with my UserValidationUpdate Request Class.

Which you and nash have provided solutions for, this is the way that it looks now .

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class UserValidationUpdate extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [

            'password' => 'min:8',
            'confirm-password' => 'min:8|same:password',
            'email' => [
                'required',
                Rule::unique('users')->ignore($this->user()->id),
            ],
        ];
    }
}

When hitting the save button with out changing anything on the user information i get

ErrorException in UserValidationUpdate.php line 33:
Trying to get property of non-object

I do not know why I am getting the error on Update of the user

I did diedump this and it returned null

$this->user()->id

i then changed it up to

$this->user

and it returned the Id of the user and when I clicked the save button without changing any of the user data. I get the flash message that the user was successfully saved. which is the correct action that should occur.

but when i deliberately change the email address to one that already exists in the database it should come back with an error alert that this email already exists right ?

When I click save it just goes to a blank page with the url showing


drac/admin/user/{id of user}

like it is trying to go back but it cannot render the page correctly.

is there anywhere else i should be looking to get more information on what is going on?

Nash's avatar

It would appear that the validation is now working then, but the previous page cannot be loaded for some reason (when the validation fails and it attempts to redirects back).

What does this page and the code that loads it (controller + view) look like?

dcaldessa's avatar

@Nash

This is my AdminUserController


<?php

namespace App\Http\Controllers;

use App\Http\Requests\UserValidationStore;
use App\Http\Requests\UserValidationUpdate;
use App\User;
use App\UserGroup;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Session;
use Illuminate\Validation\Rule;

class AdminUserController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view('admin.user.index');
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $groups = UserGroup::all();

        return view('admin.user.create',compact('groups'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(UserValidationStore $request)
    {

        $user = User::create($request->all());

        Session::flash('success', 'User successfully saved.');

        $groups = UserGroup::all();

        if ($request->get('submit') == 'saveAndClose'){
            return view('admin.user.index');
        }elseif ($request->get('submit') == 'saveAndNew'){
            return view('admin.user.create',compact('user','groups'));
        }
        return view('admin.user.edit',compact('user','groups'));
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {

    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $user= User::findOrfail($id);
        $groups = UserGroup::all();

        return view('admin.user.edit',compact('user','groups'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(UserValidationUpdate $request, $id)
    {

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

        if(empty($request->password)){
            $user->update($request->except('password'));
        }
        else{
            $user->update($request->all());
        }

        Session::flash('success', 'User successfully saved.');

        $groups = UserGroup::all();

        if ($request->get('submit') == 'saveAndClose'){
            return view('admin.user.index');
        }elseif ($request->get('submit') == 'saveAndNew'){
            return view('admin.user.create',compact('groups'));
        }
        return view('admin.user.edit',compact('user','groups'));
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

and this is the edit.blade.php

@extends('layouts.admin')
@section('styles')
    <!-- Admin styles CSS -->
    <link rel="stylesheet" href="{{asset('css/admin/admin-styles.css')}}">
@stop
@section('content')

    <div class="col-sm-12">
        <div class="row">
            {!! Form::model($user,['method'=>'PATCH','action'=>['AdminUserController@update',$user->id],'class'=>'form-validate form-horizontal']) !!}
            {!!csrf_field()!!}

            {{--Start of button panel--}}
            <div class="subhead">
                <div class="container-fluid">
                    <div id="container-collapse" class="container-collapse"></div>
                    <div class="row-fluid">
                        <div class="span12">
                            <div class="btn-toolbar" id="toolbar">
                                <div class="btn-wrapper" id="toolbar-apply">
                                    <button type="submit" name="submit" value="save" class="btn btn-small btn-success">
                                        <span class="icon-apply icon-white"></span>
                                        {{trans('admin-buttons.DRAC_BUTTON_SAVE')}}</button>
                                </div>
                                <div class="btn-wrapper" id="toolbar-save">
                                    <button class="btn btn-small" type="submit" name="submit" value="saveAndClose">
                                        <span class="icon-save"></span>
                                        {{trans('admin-buttons.DRAC_BUTTON_SAVE_CLOSE')}}</button>
                                </div>
                                <div class="btn-wrapper" id="toolbar-save-new">
                                    <button class="btn btn-small" type="submit" name="submit" value="saveAndNew">
                                        <span class="icon-save-new"></span>
                                        {{trans('admin-buttons.DRAC_BUTTON_SAVE_NEW')}}</button>
                                </div>
                                <div class="btn-wrapper" id="toolbar-cancel">
                                    <a class="btn btn-small" href="{{route('user.index')}}">
                                        <span class="icon-cancel"></span>
                                        {{trans('admin-buttons.DRAC_BUTTON_CANCEL')}}</a>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            {{--end button panel--}}
            {{--Validation check--}}
            @include('admin.partials.errorNotification')
            {{--End Validation check--}}
            {{--Success message if everything is saved successfully--}}
            @if(Session::has('success'))
                <div class="alert alert-success">
                    <button type="button" class="close" data-dismiss="alert">x</button>
                    {{Session::get('success')}}
                </div>
            @endif
            {{--end success message--}}

            <div id="tab-panel">
                <ul class="nav nav-tabs">
                    <li class="active">
                        <a href="#account_details" data-toggle="tab">Account Details</a>
                    </li>
                    <li>
                        <a href="#user_groups" data-toggle="tab">Assigned User Groups</a>
                    </li>
                    <li>
                        <a href="#basic_settings" data-toggle="tab">Basic Settings</a>
                    </li>
                </ul>

                <div class="tab-content">
                    {{--User details tab--}}
                    <div class="tab-pane active tabPosition" id="account_details">
                        <div class="col-lg-3 col-md-4">
                            <div class="form-group top-control">
                                <div class="label-container">
                                    <label for="firstName" class="control-label label-left">{{trans('admin.DRAC_ADMIN_FIRSTNAME')}} *</label>
                                </div>
                                <div class="input-control label-left">
                                    <input type="text" name="firstName" id="firstName" class="form-control" value="{{$user->firstName}}" disabled="disabled">
                                </div>
                            </div>
                            <div class="form-group top-control">
                                <div class="label-container">
                                    <label for="lastName" class="control-label label-left">{{trans('admin.DRAC_ADMIN_LASTNAME')}} *</label>
                                </div>
                                <div class="input-control label-left">
                                    <input type="text" name="lastName" id="lastName" class="form-control" value="{{$user->lastName}}" disabled="disabled">
                                </div>
                            </div>
                            <div class="form-group top-control">
                                <div class="label-container">
                                    <label for="login-name" class="control-label label-left">{{trans('admin.DRAC_ADMIN_LOGIN_NAME')}} *</label>
                                </div>
                                <div class="input-control label-left">
                                    <input type="text" name="login_name" id="login_name" class="form-control" value="{{$user->login_name}}" disabled="disabled">
                                </div>
                            </div>
                            <div class="form-group top-control">
                                <div class="label-container">
                                    <label for="password" class="control-label label-left">{{trans('admin.DRAC_ADMIN_PASSWORD')}}</label>
                                </div>
                                <div class="input-control label-left">
                                    <input type="password" name="password" id="password" class="form-control">
                                </div>
                            </div>
                            <div class="form-group top-control">
                                <div class="label-container">
                                    <label for="confirm-password" class="control-label label-left">{{trans('admin.DRAC_ADMIN_CONFIRM_PASSWORD')}}</label>
                                </div>
                                <div class="input-control label-left">
                                    <input type="password" name="confirm-password" id="confirm-password" class="form-control">
                                </div>
                            </div>
                            <div class="form-group top-control">
                                <div class="label-container">
                                    <label for="email" class="control-label label-left">{{trans('admin.DRAC_ADMIN_EMAIL')}} *</label>
                                </div>
                                <div class="input-control label-left">
                                    <input type="email" name="email" id="email" class="form-control" value="{{$user->email}}">
                                </div>
                            </div>
                            <div class="form-group top-control">
                                <div class="label-container">
                                    <label for="registration-date" class="control-label label-left">{{trans('admin.DRAC_ADMIN_REGISTRATION_DATE')}}</label>
                                </div>
                                <div class="input-control label-left">
                                    <input type="text" name="registration-date" id="registration-date" class="form-control" value="{{$user->created_at}}" disabled>
                                </div>
                            </div>
                            <div class="form-group top-control">
                                <div class="label-container">
                                    <label for="last-visit-date" class="control-label label-left">{{trans('admin.DRAC_ADMIN_LAST_VISIT_DATE')}}</label>
                                </div>
                                <div class="input-control label-left">
                                    <input type="text" name="last-visit-date" id="last-visit-date" class="form-control" disabled>
                                </div>
                            </div>
                            <div class="form-group top-control">
                                <div class="label-container">
                                    <label for="last-reset-date" class="control-label label-left">{{trans('admin.DRAC_ADMIN_LAST_RESET_DATE')}}</label>
                                </div>
                                <div class="input-control label-left">
                                    <input type="text" name="last-reset-date" id="last-reset-date" class="form-control" disabled>
                                </div>
                            </div>
                            <div class="form-group top-control">
                                <div class="label-container">
                                    <label for="password-reset-count" class="control-label label-left">{{trans('admin.DRAC_ADMIN_PASSWORD_RESET_COUNT')}}</label>
                                </div>
                                <div class="input-control label-left">
                                    <input type="text" name="password-reset-count" id="password-reset-count" class="form-control" value="{{$user->password_reset_count}}" disabled>
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="label-container">
                                    <label for="sendEmail" class="control-label label-left">{{trans('admin.DRAC_ADMIN_RECEIVE_SYSTEM_EMAILS')}}</label>
                                </div>
                                <div class="controls label-left">
                                    <fieldset class="btn-group btn-group-yesno radio" id="sendEmail">
                                            <input type="radio" id="sendEmail0" name="sendEmail" value="1" {{$user->sendEmail ? 'checked=checked' : ''}}>
                                            <label for="sendEmail0">Yes</label>
                                            <input type="radio" id="sendEmail1" name="sendEmail" value="0" {{!$user->sendEmail ? 'checked=checked' : ''}}>
                                            <label for="sendEmail1">No</label>
                                    </fieldset>
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="label-container">
                                    <label for="blockUser" class="control-label label-left">{{trans('admin.DRAC_ADMIN_BLOCK_THIS_USER')}}</label>
                                </div>
                                <div class="controls label-left">
                                    <fieldset class="btn-group btn-group-yesno radio" id="blockUser">
                                        @if($user->blockUser == 1)
                                            <input type="radio" id="blockUser0" name="blockUser" value="{{$user->blockUser}}" checked="checked">
                                            <label for="blockUser0">Yes</label>
                                            <input type="radio" id="blockUser1" name="blockUser" value="0">
                                            <label for="blockUser1">No</label>
                                        @else
                                            <input type="radio" id="blockUser0" name="blockUser" value="1">
                                            <label for="blockUser0">Yes</label>
                                            <input type="radio" id="blockUser1" name="blockUser" value="{{$user->blockUser}}" checked="checked">
                                            <label for="blockUser1">No</label>
                                        @endif
                                    </fieldset>
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="label-container">
                                    <label for="pwdreset" class="control-label label-left">{{trans('admin.DRAC_ADMIN_REQUIRE_PASSWORD_RESET')}}</label>
                                </div>
                                <div class="controls label-left">
                                    <fieldset class="btn-group btn-group-yesno radio" id="pwdreset">
                                        @if($user->reqPasswordReset == 1)
                                            <input type="radio" id="pwdreset0" name="reqPasswordReset" value="{{$user->reqPasswordReset}}" checked="checked">
                                            <label for="pwdreset0">Yes</label>
                                            <input type="radio" id="pwdreset1" name="reqPasswordReset" value="0">
                                            <label for="pwdreset1">No</label>
                                        @else
                                            <input type="radio" id="pwdreset0" name="reqPasswordReset" value="1">
                                            <label for="pwdreset0">Yes</label>
                                            <input type="radio" id="pwdreset1" name="reqPasswordReset" value="{{$user->reqPasswordReset}}" checked="checked">
                                            <label for="pwdreset1">No</label>
                                        @endif
                                    </fieldset>
                                </div>
                            </div>
                        </div>{{--end account details--}}
                    </div>
                    {{--Assigned user group tabs--}}
                    <div class="tab-pane tabPosition" id="user_groups">
                        <div class="col-sm-3">
                            <div class="checkbox-container">
                                <div class="row">
                                    @foreach($groups as $group)
                                        <div class="control-group">
                                            <div class="input-control label-left chkbox-control button">
                                                <label for="{{$group->name}}" class="form-check-label checkbox-inline align-middle">
                                                    <input type="checkbox" name="groupid[]"
                                                           {{in_array($group->id,$user->groupid) ? 'checked' : ''}}
                                                           value={{$group->id}} class="check-input">{{$group->name}}
                                                </label>
                                            </div>
                                        </div>
                                    @endforeach
                                </div>
                            </div>
                        </div>{{--end assigned user group tab--}}
                    </div>
                    {{--Basic Settings Tab--}}
                    <div class="tab-pane tabPosition" id="basic_settings">
                        <div class="col-sm-3">
                            <div class="form-group">
                                <div class="label-container">
                                    <label for="backend-language" class="control-label label-left">{{trans('admin.DRAC_ADMIN_BACKEND_LANGUAGE')}}</label>
                                </div>
                                <div class="input-control label-left">
                                    <select class="form-control" name="backend-language" id="backend-language">
                                        <option value="1">one</option>
                                        <option value="2">two</option>
                                        <option value="3">three</option>
                                        <option value="4">four</option>
                                        <option value="5">five</option>
                                    </select>
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="label-container">
                                    <label for="front-end-language" class="control-label label-left">{{trans('admin.DRAC_ADMIN_FRONTEND_LANGUAGE')}}</label>
                                </div>
                                <div class="input-control label-left">
                                    <select class="form-control" name="front-end-language" id="front-end-language">
                                        <option value="1">one</option>
                                        <option value="2">two</option>
                                        <option value="3">three</option>
                                        <option value="4">four</option>
                                        <option value="5">five</option>
                                    </select>
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="label-container">
                                    <label for="time-zone" class="control-label label-left">{{trans('admin.DRAC_ADMIN_TIME_ZONE')}}</label>
                                </div>
                                <div class="input-control label-left">
                                    <select class="form-control" name="timezone">
                                        @foreach(timezone_identifiers_list() as $timezone)
                                            <option value="{{$timezone}}"{{$timezone == $user->timezone ? 'selected' : ''}}>{{$timezone}}</option>
                                        @endforeach
                                    </select>
                                </div>
                            </div>
                        </div>
                    </div>{{--end basic settings--}}
                </div>
            </div>
            {!! Form::close() !!}
            {{--</form>--}}
        </div>
    </div>
@stop

@section('scripts')
    <script src="{{asset('js/admin/users.js')}}"></script>
@stop

Nash's avatar

Your controller and view seem pretty normal, and since your validation is either a success or tries to redirect back (like it should), there's probably nothing wrong with the request.

Besides, there's usually some sort of error message (as opposed to a blank screen). Could you be having some sort of JS problem? Does the console show anything?

dcaldessa's avatar

I ran some more tests to see if I could narrow things down. What I have found is that after successful save of creating the user it takes me to the edit page which pulls all the user info from the database.

looks like we figured things out the return for our store method was changed from

return view('admin.user.edit',compact('user','groups'));

with this code

return \redirect('admin/user/'.$id.'/edit')->with('user', $user)->with('groups',$groups);

This gets us the expected result of creating a user. redirecting to the edit page. introduce validation error by removing the email we hit save and now get the expected result of the error popping up telling us we need an email address..

it looks crude to me but it works. If there is another way of writing it please feel free to let me know ..

I thank you for all your help during this ..

Please or to participate in this conversation.