Same type of route skip if no model found?

Published 1 month ago by Shirshak

Suppose my route looks like this

Route::get('/{page_slug}','[email protected]');
// and in controller there is implicit route binding

Route::get('/{username}','[email protected]');
// in controller there is implicity route binding

The problem is if pages don't exist it will immediately show 404 pages . Is there any simple way if there is no pages with page slug move to username and even if username is not found then skip to another.

Thanks

Best Answer (As Selected By Shirshak)
Sanctuary

I suppose you could do something like this:

Route::get('/{value}', function($value) {
    if ($page = Page::find($value)) {
        return app('App\Http\Controllers\PagesController')->show($page);
    }
    else if ($user = User::find($value)) {
        return app('App\Http\Controllers\ProfileController')->show($user);
    }

    // do some more stuff
});

But that seems kinda hacky, and I'd personally recommend just doing domain.com/users/{user} to avoid potential problems like having a user with the same name as one of your pages, or vice versa.

If you're doing this on the root level of all your routes (/), be sure to put it at the bottom so that it doesn't conflict with your others. Also be sure to call abort(404) after all your conditionals to ensure you get 404s if none of them are met.

If anyone else has a better solution, I'd also like to hear it, as I'm a bit curious now too. :)

Sanctuary

I suppose you could do something like this:

Route::get('/{value}', function($value) {
    if ($page = Page::find($value)) {
        return app('App\Http\Controllers\PagesController')->show($page);
    }
    else if ($user = User::find($value)) {
        return app('App\Http\Controllers\ProfileController')->show($user);
    }

    // do some more stuff
});

But that seems kinda hacky, and I'd personally recommend just doing domain.com/users/{user} to avoid potential problems like having a user with the same name as one of your pages, or vice versa.

If you're doing this on the root level of all your routes (/), be sure to put it at the bottom so that it doesn't conflict with your others. Also be sure to call abort(404) after all your conditionals to ensure you get 404s if none of them are met.

If anyone else has a better solution, I'd also like to hear it, as I'm a bit curious now too. :)

Shirshak

@Sanctuary Yes but even though it is hacky the only problem i find is Route cannot be cached as you used clousure. I guess i need to make separate controller for such task only right? I guess framework don't have ability to skip routes on conditions

Sanctuary

Yeah, you could just create a controller method with the stuff from the closure, yes. There's some docs on single action controllers if you haven't already seen them.

I may be wrong, but as far as I'm concerned, Laravel doesn't have anything specific to handle this kind of situation.

maslauskast

Maybe you could use regular expression constraints:

https://laravel.com/docs/5.6/routing#parameters-regular-expression-constraints

But I agree with @Sanctuary , you should separate those routes to domain.com/users/{user} and domain.com/pages/{page}

Shirshak

@maslauskast i agree but its not flexible.

Snapey
Snapey
1 month ago (924,495 XP)

you end up building your own route controller that tests for each condition and then delegates to the correct controller

Please sign in or create an account to participate in this conversation.