5

These are my routes for which I am facing problem

Route to get the list of registered places in a particular city

Ex: http://localhost:8000/London, http://localhost:8000/London/Restaurants

Route::group(['namespace' => 'Page'], function() {
    Route::group(['prefix' => '{city}', 'where'  => ['city' => '[\w\d]+']], function() {
        Route::get('/', 'CityPageController@showCityPage')->name('cityPage');
    });
});

Route to get a particular user profile and its details such as reviews, photos etc.

Ex: http://localhost:8000/John, http://localhost:8000/John/reviews, http://localhost:8000/John/photos

Route::group(['namespace' => 'User'], function() {
    Route::group(['middleware' => 'verified'], function() {
        Route::group(['prefix' => '{username}', 'where'  => ['username' => '[\w\d]+']], function() {
            Route::get('/', 'ProfileController@showProfilePage')->name('profilePage');
            Route::get('/reviews', 'ReviewController@showReviewPage')->name('reviewPage');
            Route::get('/photos', 'ImageController@showPhotoPage')->name('photoPage');
        });
    });
});

The problem is that both of these routes are not working simultaneously.

The route the resides above the other takes precedence over the other route.

how to solve this problem of routing.

Edit

I know there is a way to achieve this functionality but I don't know how. Any help is appreciated.

Prateek
  • 1,229
  • 17
  • 31

4 Answers4

6

Note: If you haven't, firstly I recommend to create a unique slug field on database first that will appear on url

Your route file

Route::get('{slug1}', 'PageController@singleSlug'); # slug 1 has to be unique i.e. username and cityname
Route::get('{slug1}/{slug2}', 'PageController@doubleSlug'); # combination of slug1 and slug2 has to be unique

The controller functions

public function singleSlug($slug1)
{
    $user = User::where('name', $slug1)->first();
    if ($user) {
        return view('user')->compact('user');
    }

    $city = City::where('name', $slug1)->first();

    if ($city) {
        return view('city')->compact('city');
    }

    abort(404); # neither user nor city
}



public function doubleSlug($slug1, $slug2)
{
    // check the slug2 as this value is always defined by the system
    switch ($slug2) {
        case 'Restaurants':
            $city = City::with('restaurants')->where('name', $slug1)->first();
            if ($city) {
                $viewName = 'city_restos_listing';
                $viewData = $city;
            }
            break;

        case 'reviews':
            $user = User::with('reviews')->where('name', $slug1)->first();
            if ($user) {
                $viewName = 'user_reviews_listing';
                $viewData = $user;
            }
            break;

        case 'photos':
            $user = User::with('photos')->where('name', $slug1)->first();
            if ($user) {
                $viewName = 'user_photos_listing';
                $viewData = $user;
            }
            break;

        default:
            abort(404); # the slug 2 is incorrect
            break;
    }
if(isset($viewName)) {
    return view($viewName)->compact('viewData');
  } else {
    abort(404); # user or city not found
 }
}
Community
  • 1
  • 1
  • 1
    This is the correct answer, but I'll add that this is really inefficient because you have to do at least one DB round trip on each request (even if you're just serving up a static page). You are much better off using a `/user` or `/city` prefix as in the other answers. – solidau Jan 14 '20 at 21:19
  • @Hášíl Páůďýál This is the correct answer but I find a little difficulty in implementing it. I will be highly thankful to you if you elaborate on this answer a little more. It will be helpful to me and other users. – Prateek Jan 17 '20 at 13:40
5

from Laravels point of view, both urls are the same:

{property}/ having different property names city and username doesn't make a differance because laravel will not understand that london is a city and say Prateek is a username.

A better approach I would suggest is to add an identefier of the model name before the prefix: EX. Route::group(['prefix' => 'users/{username}' ... instead of your approach and city before the city route.

have a look at this: https://laravel.com/docs/6.x/controllers#resource-controllers

Fahd Yousri
  • 401
  • 3
  • 12
2

add a prefix to distinguish these two kinds of route Route::group(['prefix' => 'users/{username}' and Route::group(['prefix' => 'cities/{city}'

Wahyu Kristianto
  • 8,719
  • 6
  • 43
  • 68
0

An easy way to solve this issue :

Route::group(['namespace' => 'Page'], function() {
    Route::group(['prefix' => 'city/{city}', 'where'  => ['city' => '[\w\d]+']], function() {
        Route::get('/', 'CityPageController@showCityPage')->name('cityPage');
    });
});

Route::group(['namespace' => 'User'], function() {
    Route::group(['middleware' => 'verified'], function() {
        Route::group(['prefix' => 'profile/{username}', 'where'  => ['username' => '[\w\d]+']], function() {
            Route::get('/', 'ProfileController@showProfilePage')->name('profilePage');
            Route::get('/reviews', 'ReviewController@showReviewPage')->name('reviewPage');
            Route::get('/photos', 'ImageController@showPhotoPage')->name('photoPage');
        });
    });
});
Foued MOUSSI
  • 4,643
  • 3
  • 19
  • 39