Laravel 5 conditional routing and multiple control

2019-08-11 06:48发布

问题:

So basically my app has two types of dynamic url..

  1. app.com/{page}
  2. app.com/{user}

Both having their own controllers

  1. PageController@index
  2. User\ProfileController@index

But I'm struggling to get this working.

I have tried a few different methods. Here are two I have tried..

Route::get('{slug}', function($slug) {
    if (App\Page::where('slug', $slug)->count()) {
        // return redirect()->action('PageController@index', [$slug]);
        // return App::make('App\Http\Controllers\PageController', [$slug])->index();
        return 'Page found';
    } else if (App\User::where('username', $slug)->count()) {
        // return redirect()->action('User\ProfileController@index', [$slug]);
        // return App::make('App\Http\Controllers\User\ProfileController', [$slug])->index();
        return 'User found';
    } else {
        return abort(404);
    }
});

I feel I should be doing this with middleware/filters. Any help would be great. Thanks.

回答1:

I think you could achieve what you after with Route::group using a middleware to filter if it is a page or a user.

Route::group(['middleware' => 'isPage'], function () {
    Route::get('{slug}', ['as'=> 'pages.show', 'uses' => 'PageController@show']);
});

Route::group(['middleware' => 'isUser'], function () {
    Route::get('{slug}', ['as'=> 'users.show', 'uses' => 'User\ProfileController@show']);
});


回答2:

If you were using slugs for the Pages and ids for the Users, your idea of handling the issue might make more sense, but since you are using slugs for both the pages and the users, I strongly suggest you try a different approach. Why not declare two routes? Why not use the "show" methods of the respective controllers while you are at it, and keep in line with conventions for resources?

Route::get('pages/{slug}', ['as'=> 'pages.show', 'uses' => 'PageController@show']);
Route::get('users/{slug}', ['as'=> 'users.show', 'uses' => 'User\ProfileController@show']);

And if you really want to keep your "root-slug-respective-redirect" functionality you could write afterwards:

Route::get('{slug}', function($slug) {
    if (App\Page::where('slug', $slug)->count()) {
        return redirect(route('pages.show', $slug));
    } else if (App\User::where('username', $slug)->count()) {
        return redirect(route('users.show', $slug));
    }
    return abort(404);
});

I do advise against it though, as it seems like a waste of queries.

Here are the docs on Laravel RESTful resource controllers for good measure.