3

I have a PagesController with one action: view. This action accepts a page argument.

What I want to achieve:

Have a routes example.com/about and example.com/foobar. When one of this routes is triggered, pass a value predefined in routes file to PagesController@view.

In my routes file:

Route::get('about', function () {
    return App::make('App\Http\Controllers\PagesController')->view('about');
})->name('aboutPage');

Route::get('foobar', function () {
    return App::make('App\Http\Controllers\PagesController')->view('foobar');
})->name('foobarPage');

It works as expected, but I want to know is there a better and more proper way to achieve the same functionality?

Alok Patel
  • 7,842
  • 5
  • 31
  • 47
user1327
  • 938
  • 3
  • 10
  • 28

5 Answers5

4

Pass your pages as route parameter:

Route::get('{page}', 'PagesController@view');

//controller
public function view($page)
{
    //$page is your value passed by route;
    return view($page);
}
Phargelm
  • 688
  • 5
  • 16
  • Thanks, but in this case every request to `domain.com/something` will trigger `PagesController@view`. Maybe there is a way to constrain possible values of `{page}`? – user1327 Jul 29 '16 at 11:23
  • 2
    You can check if requested view exists like this: `if(view()->exists($page)) { return view($page)} else {abort(404)}`. Another way is adding regexp to your route `Route::get('{page}', 'PagesController@view')->where('page', '(about)|(foobar)');` but in this case you should manually enumarate all existing pages – Phargelm Jul 29 '16 at 11:34
2

So you just want an argument to your action. You can use optional parameters if that argument can be empty. You can read more about it here.

Route::get('{argument?}', 'PagesController@view')->name('page');

And in your PagesController:

public function view($argument = 'default') {
    // Your logic
}
Can Vural
  • 2,222
  • 1
  • 28
  • 43
2

The accepted answer is what you want based on what you are doing.

If you really wanted a hardcoded value you can use the 'actions' array part of the route if you wanted.

Route::get('something', ['uses' => 'Controller@page', 'page' => 'something']);

public function page(Request $request)
{
    $page = $request->route()->getAction()['page'];
    ...
}

asklagbox - blog - random tips and tricks

lagbox
  • 48,571
  • 8
  • 72
  • 83
  • 1
    You can even pass 'page' like `getAction('page')`. See https://laravel.com/api/6.x/Illuminate/Routing/Route.html#method_getAction – Ryan Jan 28 '20 at 14:42
1

If you don't need the names of the routes like in your example

->name('foobarPage');

you can use something like this

Route::get('{page_name}','PagesController@view')->where('page_name', '(about)|(foobar)');

This will accept only the values passed in the regular expression for the page_name parameter. Other routes will throw a 404 error. I should mention that this technique seems to be valid for applications with one level of url nesting only and should NOT be used as a pattern.

George Koniaris
  • 324
  • 2
  • 9
1

From what I can see above if all you are doing is showing the correct view I would go for

Route::get('{page}', function($page)
{
    if (view()->exists($page)) { 
        return view($page);
    } 
    return abort(404);
});

This prevents you even needing a method in your controller.

Matt Stephens
  • 922
  • 1
  • 6
  • 24