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?
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?
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();
}
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community