Reputation: 5782
My index page displays all images from my images table with the newest submissions on top. I'm trying to add some basic filtering so I can grasp the concept but I'm doing something wrong. My idea is:
Add 2 <a>
elements with URLs to www.domain.com
and www.domain.com/ascending
. If the user goes to www.domain.com
, the images will be displayed in descending order and if he goes to www.domain.com/ascending
they will be displayed in ascending order.
Then I make my home route Route::get('/', 'PagesController@index')->name('home');
have an optional parameter like Route::get('/{filter?}', 'PagesController@index')->name('home');
Based on the optional parameter, I'll send different $images
variable to the view:
public function index($filter){
switch($filter) {
case 'ascending' : $images = Image::orderBy('created_at', 'asc')->get();break;
default : $images = Image::orderBy('created_at', 'desc')->get();
}
return view('home', ['images' => $images]);
}
As soon as I did this, I got 2 problems so far:
Firstly, when I go to www.domain.com
, I get "Type error: Too few arguments to function App\Http\Controllers\PagesController::index(), 0 passed and exactly 1 expected"
Secondly, after adding the optional parameter to the route Route::get('/{filter?}', 'PagesController@index')->name('home');
I get send to my index page even when I'm going to URLs like http://example.com/admin
or http://example.com/albums
.
I believe this happens because my code assumes that /admin
and /albums
are the optional parameter in my http://example.com url and not a separate url like it should be.
Route::get('/{filter?}', 'PagesController@index')->name('home');
Route::get('/image/{id}', 'PagesController@specificImage')->name('specificImage');
Route::get('/tags', 'PagesController@tags')->name('tags');
So even if I go to the tags route, the index view will be displayed instead of the tags view.
Upvotes: 0
Views: 282
Reputation: 7334
First and foremost, using query parameter looks best for filtering in this situation instead of having two (or more) url endpoints.
However, if you want to stick with your implementation there are few things to do:
Declare your routes without leading slash, e.g:
Route::get('{filter?}', 'PagesController@index')->name('home')
Not so sure this does make any difference though, but something I personally watchout for (slashes everywhere)
Use optional path variable with restricted values, by using where()
after the route declaration:
Route::get('{filter?}', 'PagesController@index')->name('home')->where('filter', 'ascending|');
It accepts ascending or nothing.
Pass a default parameter to your controller method:
public function index($filter = null)
{
.....
}
Just in case nothing was passed. This is one of the important points to note with optional path variables.
Finally, you can avoid if
statement totally, by using a Ternary operator before making the query:
public function index($filter = null){
$order = $filter === 'ascending' ? 'asc' : 'desc';
$images = Image::orderBy('created_at', $order)->get();
return view('home', ['images' => $images]);
}
Upvotes: 0
Reputation: 381
you can do this www.domain.com?orderby=asc
Route::get('/', 'PagesController@index')->name('home');
public function index(Request $request){
$images = array();
$images = Image::orderBy('created_at', $request->get('orderBy') ?? 'desc')->get();
return view('home', ['images' => $images]);
}
Upvotes: 3
Reputation: 909
I suggest you use get params in this case to avoid conflicting urls. So that request to /
should now be
/?order=asc
or /?order=desc
and rather switch the get param order
to know whether to show the page in descending or ascending order.
Upvotes: 1