clueless's avatar

How do you route old .php urls in Lumen

I'm moving an old site to Lumen and I need to 301 redirect some old URLs.

i.e. something.php?id=1 -> somethings/1.

I've done quite a bit of googling and even asked this question on stackoverflow. But nothing seems to work.

Can anyone point me to the right direction?

edit: Including some code I've tried here.

$app->get('/something.php?id={id}', function ($id) {
    redirect()->route('somethings', ['id' => $id]);
});
$app->get('somethings/{id}', [
    'as' => 'somethings', 'uses' => 'SomeController@show'
]);
0 likes
12 replies
phildawson's avatar

@clueless I think you just need to add return inside the closure.

However I would definitely use the servers rewrite module to do this bit rather than than the application.

For nginx it would be something like this as an example

rewrite ^/something.php?id=(.*)$ /somethings/$1 permanent;
pmall's avatar

I don't think you can use the url query parameters in the pattern. I would do :

$app->get('/something.php', function (Request $request) {
    return redirect()->route('somethings', ['id' => $request->id]);
});
phildawson's avatar

@pmall yeah that's fine as an example this would display foo for /foo

$app->get('{id}', function($id){ return $id; });

Edit: Yep this won't work with query string params.

pmall's avatar

@phildawson I'm just not sure the url query parameters are included in the url matched to the pattern.

phildawson's avatar

@pmall ah yes I think you are correct, it would have to be like this as you say.

$app->get('/something.php', function (Illuminate\Http\Request $request) {
    return redirect()->route('somethings', ['id' => $request->id]);
});

I'd still go for the server approach though which would be far more efficient. :)

clueless's avatar

@phildawson I tried your suggestions but none seem to work. I keep getting that pesky No input file specified error.

Neither putting this in the nginx config

rewrite ^/something.php?id=(.*)$ /somethings/$1 permanent;

Nor putting this snippet in the routes work

$app->get('/something.php', function (Illuminate\Http\Request $request) {
    return redirect()->route('somethings', ['id' => $request->id]);
});

Nothing seems to have any effect, homestead simply refuses to match something.php with anything.

phildawson's avatar
Level 26

@clueless sorry that's my bad the query string is stored in $args. I've tested the code too and it won't work in a standard setup as everything is being caught to index.php

I've just tried the following on my setup to confirm it works, does this work for you?

    location ~ ^/something\.php$ {
        if ($arg_id ~ ([0-9]+)$) {
            set $id $1;
            rewrite ^ /somethings/$id? permanent;
        }
    }

This will need to be above location ~ \.php$ { for it to be checked first.

1 like
clueless's avatar

Hi, sorry about the late response, got super busy with something else.

I can confirm that this works:

location ~ ^/something\.php$ {
    if ($arg_id ~ ([0-9]+)$) {
        set $id $1;
        rewrite ^ /somethings/$id? permanent;
    }
}

Unfortunately, a new requirement was added. The solution has to be included with the repo. Given my inexperience, I'm not really sure if this is possible on nginx servers.

Is it possible to put this condition in a file inside the /public folder? Kind of like how .htaccess works like that?

willvincent's avatar

You could so something like this in your nginx config:

...

include /path/to/nginx-config/in/your/repo;


location ~ \.php$ {
...

Then in that file, have all your redirects.

Of course, if you change that file, you'll need to restart nginx for the changes to take effect, it's not going to be parsed on every request like htaccess files are.

1 like
clueless's avatar

Now this is just silly. I need your help on this again, guys.

It seems that doing redirecting the user from something.php?id=1 to somethings/1 is not an option.

So I need to be able to do this without the URL changing. Is that possible? I tried removing permanent from this line

rewrite ^ /somethings/$id? permanent;

But I'm just getting an application error.

NotFoundHttpException in Application.php line 1205:

I did some research and it looks like by replacing the $app->run line on public/index.php like so:

$request = Illuminate\Http\Request::capture();
$app->run($request);

The route is matched to this one:

$app->get('something.php', function () {
    dd("HERE");
});

And I get "HERE" on the page. Unfortunately, I can't seem to get the ID. I feel like I'm so close, and yet I can't figure it out.

Please help me.

willvincent's avatar

So, if you add a try_files to your location php in the nginx config, you should be able to pass those old paths in properly and avoid the no input file issue...and not have to change index.php

    location ~ \.php$ {
        try_files $uri $uri/ /index.php?$args;

   ...

Then in your route, you want to inject the request object:

$app->get('campaign.php', function ( \Illuminate\Http\Request $request ) {
  dd($request->get('id'));
});
willvincent's avatar

I was thinking maybe you could intercept these requests with middleware and then internally change the routes to match whatever your new routes are, but that might be more effort than it's worth. Instead, maybe just throw all these old ones into their own routes file, and require that in your main routes file (just to keep the old stuff out of the way of progress) :)

Please or to participate in this conversation.