Support the ongoing development of Laravel.io →
Requests Forms Validation

Hello,

I'm having some trouble realizing a bit of logic in my application. In short, I have a user update form to update the name and email of a given user. In my form request, the rules for both fields are required and unique. But for each field I want the unique rule to ignore the row in the DB for the user itself, so when I update my email but leave my user name field as it is (pre-filled with my current user name) it should pass validation and vice versa.

BUT HERE IS THE CATCH: Of course I researched how to do that, and you'll find tons of information regarding that topic, even in the official documentation they cover it in the unique rule description.

For example: https://laravel.com/docs/5.4/validation#rule-unique https://laracasts.com/discuss/channels/requests/laravel-5-validation-request-how-to-handle-validation-on-update http://stackoverflow.com/questions/22405762/laravel-update-model-with-unique-validation-rule-for-attribute

However, as far as I understand in the official documentation as well as in every google result I found regarding that topic, they always assume that the currently logged in user is editing / updating his/her own profile. This is why in the official documentation, they do this:

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

To my understanding (and I tested this), $user->id in this case refers to the currently logged in user's id. This is where my problems start. Because in my case, I don't want to edit my own profile, but every user profile there is. It's a piece of logic in my backend (admin interface). I want to have the ability to edit every user's name and email.

So with that in mind, the above code block doesn't work.

I fixed my problem. However I'd like to ask you guys if there is an easier way to achieve this.

This is how I fixed it, my controller method:

    /**
     * Show a specific user.
     *
     * @return \Illuminate\Http\Response
     */
    public function show(User $user)
    {
        $roles = Role::whereDoesntHave('users', function ($query) use ($user) {
            $query->where('id', '=', $user->id);
        })->pluck('display_name', 'id');

        Session::put('editableUser', $user->id);

        return view('admin.users.show', compact('user', 'roles'));
    }

so this is where I prepare the user data to display it in the view. Take a look at the line where I put the ID of the user I'm working with in the session (I have a form to edit the user in the admins.users.show view).

Then after I submit the form it fires a FormRequest, and here is the rules method:

    public function rules()
    {
        $user_id = $this->session()->get('editableUser');

        return [
            'username'  => ['required', Rule::unique('users', 'name')->ignore($user_id)],
            'email'     => ['required', 'email', Rule::unique('users', 'email')->ignore($user_id)],
        ];
    }

So what I'm doing is, I get the user ID from the session and apply the officially documented rule, but instead of the currently logged in user I pass in the ID of the sessioned user, or in other words the user I'm trying to edit.

It's working flawlessly. However, I'm wondering if I did it correctly, or if I missed something obvious and if this can somehow be achieved easier?

Last updated 3 years ago.
0

Quick Edit: Ok I'm one step forward, I realized that $this->user is the currently being edited users' name. So I changed my rules method to this:

    public function rules()
    {
        $user = User::where('name', '=', $this->user)->first();

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

I don't need to use the session anymore. It's still working as far as I can tell. However, would you do it like that?

0

based on your reply, I tried to view $this->user in my case it contains user id so I do not need to do this query User::where('name', '=', $this->user)->first();

I am not sure how id end up on $this->user when I check other models I get same result for example model Task I get $this->task that contains id, however now unique ignore current user works for email field

thank you

this is my code

<?php

namespace App\Http\Requests\User;

use Illuminate\Foundation\Http\FormRequest;

class UpdateUserRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return auth()->user()->can('user-update');
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required',
            'email' => 'required|email|unique:users,email,'.$this->user,
            'address' => '',
            'work_number' => 'numeric',
            'personal_number' => 'numeric',
            'password' => 'sometimes',
            'password_confirmation' => 'sometimes',
            'image_path' => 'mimes:jpeg,jpg,png,gif|max:100000',
            'roles' => 'required',
            'departments' => ''
        ];
    }
}

controller action

    /**
     * @param $id
     * @param UpdateUserRequest $request
     * @return mixed
     */
    public function update($id, UpdateUserRequest $request)
    {
        $this->users->update($id, $request);
        Session()->flash('flash_message', 'User successfully updated');
        return redirect()->back();
    }
0

Sign in to participate in this thread!

Eventy

Your banner here too?

minikN minikn Joined 8 Dec 2014

Moderators

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2025 Laravel.io - All rights reserved.