I am using Laravel 8 and validate my requests with the form request validation. However, I have a strange problem. Before I am going to describe my problem I will paste my routes and my validation class here:
routes:
Route::post('users', ['as' => 'user.search', 'uses' => 'UserController@indexSearch']);
Route::post('user/name', ['as' => 'user.name.exists', 'uses' => 'UserController@nameExists']);
Route::post('user/email', ['as' => 'user.email.exists', 'uses' => 'UserController@emailExists']);
Route::post('user/email/check', ['as' => 'user.email.check', 'uses' => 'UserController@emailCheck']);
Route::get('user/{user:name}', ['as' => 'user.show', 'uses' => 'UserController@show']);
Route::get('user/{user:name}/einstellungen', ['as' => 'user.settings', 'uses' => 'UserController@showSettings']);
Route::get('user/{user:name}/produkte', ['as' => 'user.products', 'uses' => 'UserController@userProducts']);
Route::post('user/{user:name}/produkte', ['as' => 'user.products.post', 'uses' => 'UserController@userProducts']);
Route::get('user/{user:name}/saved/produkte', ['as' => 'user.marked.products', 'uses' => 'UserController@userMarkedProducts']);
Route::post('user/{user:name}/saved/produkte', ['as' => 'user.marked.products.post', 'uses' => 'UserController@userMarkedProducts']);
Route::post('user/{user:name}/avatar/upload', ['as' => 'user.avatar.update', 'uses' => 'UserController@update']);
Route::post('user/{user:name}/avatar/valid', ['as' => 'user.avatar.valid', 'uses' => 'UserController@validAvatar']);
Route::post('user/{user:name}/avatar/löschen', ['as' => 'user.avatar.delete', 'uses' => 'UserController@deleteAvatar']);
Route::post('user/{user:name}/update/password', ['as' => 'user.password.change', 'uses' => 'UserController@updatePassword']);
Route::post('user/{user:name}/validate/password', ['as' => 'user.password.validate', 'uses' => 'UserController@validatePassword']);
This is my FormRequest
validation which checks if the user is authorized to perform this request and if the given data are valid. As you can see, I check if the Auth::user()->name
is the same as the requested user ($this->user->name
) to change the image. Because only the owner of his profile image should be allowed to change is profile image.
class UserAvatarUpdateRequest extends FormRequest
{
public function authorize()
{
dump(array('auth' => Auth::user()->name, 'requested' => $this->user));
if(Auth::check() && Auth::user()->name == $this->user->name){
return true;
}
return false;
}
public function rules()
{
return [
'avatar' => [
'required',
'image',
'max:5000',
'mimes:jpeg,png,jpg',
Rule::dimensions()->minWidth(200)->minHeight(200)->ratio(1)
],
];
}
}
Now I will come to the problem. As you can see I have several routes for my user and there is one route called user.avatar.valid
and another route called user.avatar.update
.
Both routes, user.avatar.valid
and user.avatar.update
are using the FormRequest
validation class I have pasted above. Basically user.avatar.valid
is being called before the user submits the form to check if the uploaded image is valid. I know, I also could do this in one request but that's not possible because I am using vee-validate
for Vuejs to validate if the form is valid.
However, thats not the probleme here. The problem is that when calling the user.avatar.valid
route my dump echos for the key requested
the name
of the requested user. But, when performing a request for user.avatar.update
I don't get the name
of the user but rather the user object
which contains the id
, name
, email
and so on.
But exactly this is the point... when trying to call user.avatar.update
I get a 403
error (forbidden) because $this->user
is not equal to Auth::user()->name
. Obviously it is not the same when I compare a string
(name) to the user object
.
However, when calling user.avatar.valid
it passes because here I get the name
when calling $this->user
and not the user object
.
But why is that?
When I change $this->user
to $this->user->name
I get the actual name for the user when calling the user.avatar.update
route but on the other side I get a 500
error when calling the user.avatar.valid
route because it says Trying to get property 'name' of non-object
...
Does anybody has an idea where the problem here is and how to fix this?
Kind regards and thank you!
Make sure you are typehinting the property in your controller's method signature properly for Route Model Binding. If not you will just get the value of the segment, the name of the user, instead of the User model since the Implicit Model Binding won't take place:
public function validAvatar(User $user) { ... }
Laravel 8.x Docs - Routing - Route Model Bindings - Implicit Binding