Back

Updating another user and ignoring its name/email when validating


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?

minikN replied 3 months ago

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?


Sign in to participate in this thread!



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