Reputation: 2120
Not actually a problem, I think I can handle, but I want to know if this is behaving as expected.
I have a database table named users
, then I created the Model and the UserController as a resource with
php artisan make:controller UserController --resource
It created the expected routes (index, store, create, show, update, destroy and edit), some GET some POST.
So now I want to create a new route that gives me the user's avatar (an image I previously stored using the Storage methods)
So I create it in the /routes/web.php file as:
Route::get('/user/avatar/{id?}', 'UserController@avatar')->name('user.avatar');
I know the function works, if I go to http://localhost/user/avatar/1 it returns the image associated to user 1. Now the thing is, I want the parameter to be optional (nullable), if I don't get the id then I'll serve the \Auth::user()->id
image.
The problem is whwn I go to http://localhost/user/avatar/ it gaves me an error (I won't print it here, because it isn't related), it looks like it is trying to go to the GET's /user/{id} route that was created with the resource, and it is treating "avatar" as the {id}.
So I know, I should take out the line Route::resource('user', 'UserController');
and create each route individually, right?
My question is, is this how it is supposed to work? should I create other, say, HelperController where I could point an /avatar/{id?} route?
EDIT: The artisan route:list output regarding to user is:
| | GET|HEAD | user | user.index | App\Http\Controllers\UserController@index | web |
| | POST | user | user.store | App\Http\Controllers\UserController@store | web |
| | GET|HEAD | user/avatar/{id?} | user.avatar | App\Http\Controllers\UserController@avatar | web |
| | GET|HEAD | user/create | user.create | App\Http\Controllers\UserController@create | web |
| | GET|HEAD | user/{user} | user.show | App\Http\Controllers\UserController@show | web |
| | PUT|PATCH | user/{user} | user.update | App\Http\Controllers\UserController@update | web |
| | DELETE | user/{user} | user.destroy | App\Http\Controllers\UserController@destroy | web |
| | GET|HEAD | user/{user}/edit | user.edit | App\Http\Controllers\UserController@edit | web |
+--------+-----------+------------------------+------------------+------------------------------------------------------------------------+--------------+
Error is:
ErrorException (E_ERROR)
Trying to get property 'name' of non-object (View: D:\Dropbox\_www\reco\resources\views\user\profile.blade.php)
Previous exceptions
Trying to get property 'name' of non-object (0)
This is in a $user->name
call, $user
is undefined, and I know what causes it, it is the find($id)
inside show (in the Controller) which is getting nothing, because it is searching for "avatar" as id.
In fact, if I change the find()
for findOrFail()
it gives me the expected 404 error. So I'm pretty sure that it is interpreting avatar as the id.
Upvotes: 1
Views: 415
Reputation: 983
You have to define your most explicit routes first:
Route::get('/user/avatar/{id?}', 'UserController@avatar');
Route::resource('user', 'UserController');
Why? Because route resource creates a GET user/{user}
route and if you register resource route first, Laravel will look at the url user/avatar/1
and think that the avatar
part is actually the ID of user.
It's just a quirk of laravel.
Upvotes: 5