5

I have a basic route that looks like this:

Route::prefix('/group')->group(function () {
    // Some routes here
    Route::prefix('/{uuid}')->group(function () {
        // Some routes here
        Route::get('/user/{id}', 'Controller@preview')->name('view-user')->where('id', '[0-9]+');
    }
}

The logic is that I want the id to be only numerical value. What I want to do now is, to declare a redirection to this, if the value is non-numerical. Let's say the input of id is fs. In that case I would want it to redirect to id with value 1.

I tried using Route:redirect, but could not make it work. It looks something like this:

Route::redirect('/group/{uuid}/user/{id}', '/group/{uuid}/user/1')->where('id', '[^0-9]+');

I would prefer to put the redirect inside the groups, but it can be outside if this is the only way. Any help will be greatly appreciated.

What happens is, that I get a 404 error if I have the route redirect declared.

EDIT: I want to do it in the routes/web.php file. I know how to do it in the controller, but it is not what I need in the current case. Closures are not an option either, because that would prevent routes caching.

Martin Dimitrov
  • 1,304
  • 1
  • 11
  • 25
  • 1
    You can use [Regular Expression Constraints](https://laravel.com/docs/master/routing#parameters-regular-expression-constraints) to only allow numerical values – brombeer Nov 28 '19 at 11:37
  • @kerbholz That is indeed a good idea, but in my case it would not work, as in order to cache the routes, there cannot be closures. – Martin Dimitrov Nov 28 '19 at 11:38
  • Use a ternary with regular expression in where clause maybe? – user3532758 Nov 28 '19 at 11:49
  • @user3532758 What exactly do you have in mind? – Martin Dimitrov Nov 28 '19 at 11:50
  • Maybe I spoke too soon hehe. I was thinking use something like is_string but don't think it will work. Or maybe you can perhaps write a middleware? Not an option? – user3532758 Nov 28 '19 at 11:57
  • 1
    You can create a Route in routes/web.py that catches non-digit ids and redirect this to 'view-user' with id=1 – ege Nov 28 '19 at 12:12
  • 2
    @ege This is exactly what I am trying to do, but I don't know how. If you could give a code sample it will be greatly appreciated. – Martin Dimitrov Nov 28 '19 at 12:17
  • @MartinDimitrov I have added a code example below, let me know how it works out. https://stackoverflow.com/a/59089181/2784375 – ege Nov 28 '19 at 12:43

4 Answers4

3

You declared it inverted.

In Laravel you can redirect passing parameters in this way:

You can pass the name instead of the url and simply pass variables.

Redirect::route('view-user', [$uuid, $id])

Luca Rossi
  • 746
  • 5
  • 18
  • I am not asking how to make a redirect, but how to declare a redirection rule in `web.php` file. I want the entire logic to be in the `routes/web.php file`, not in the controller. – Martin Dimitrov Nov 28 '19 at 11:42
3

I think that you can do it inside of the controller of the router, with a logic like this:

class Controller {
    // previous code ..

    public function preview($uuid, $id) {
        if(! is_numeric($id))
            return redirect("/my-url/1");

        // run the code below if $id is a numeric value..
        // if not, return to some url with the id = 1
    }
}

I think that there is no way to override the 'where' function of laravel, but I guess that have something like that in Routing Bindings:

Alternatively, you may override the resolveRouteBinding method on your Eloquent model. This method will receive the value of the URI segment and should return the instance of the class that should be injected into the route:

/**
 * Retrieve the model for a bound value.
 *
 * @param  mixed  $value
 * @return \Illuminate\Database\Eloquent\Model|null
 */
public function resolveRouteBinding($value)
{
    return $this->where('name', $value)->first() ?? abort(404);
}

But it's require that you manage consise model's values instead of ids of whatever you want.

  • I have updated again the question. I had stated before in a comment below, closures are not an option for me. I have now put it in the question. – Martin Dimitrov Nov 28 '19 at 12:05
3

Following up on the comment

You can create a Route in routes/web.php file that catches non-digit ids and redirect this to 'view-user' with id=1

It would look something like this

Route::get('/group/{uuid}/user/{id}', function ($uuid, $id) {
  return redirect('view-user', ['uuid' => $uuid, 'id' => 1]);
})->where('id', '[^0-9]+');

// and then below have your normal route

Route::get('/group/{uuid}/user/{id}', 'Controller@preview')->name('view-user')->where('id', '[0-9]+');

Update

Following you comment that you do not want to use closures.

Change the "bad input route" to

Route::get('/group/{uuid}/user/{id}', 'Controller@redirectBadInput')->where('id', '[^0-9]+');

and then add the method in class Controller:

public function redirectBadInput ($uuid, $id) {
  return redirect('view-user', ['uuid' => $uuid, 'id' => 1]);
}

You can see more in this SO thread about redirects and caching.

Haseeb Zulfiqar
  • 316
  • 3
  • 11
ege
  • 774
  • 5
  • 19
1

assign route name in route as like.

return Redirect::route('view-user', ['uuid'=>$uuid,'id'=>$id]);

As you want in web.php file then.

Route::get('/group/{uuid}/user/{id}', function($uuid, $id){
    echo $uuid;
    echo $id;
})->name('view-user')->where('id', '[0-9]+');
Dilip Hirapara
  • 14,810
  • 3
  • 27
  • 49