PHP Slim-3:如何在内部重定向到另一条路由
PHP Slim-3: How to redirect internally to another route
我有一条如下所示的通用路线 -
$app->map(['GET', 'POST'], "/", function (\Slim\Http\Request $request, \Slim\Http\Response $response) use ($app) {
// Some random version 1 processing here ...
}
我有一个 v2 版本,如下所示 -
$app->map(['GET', 'POST'], "/api/v2", function (\Slim\Http\Request $request, \Slim\Http\Response $response) use ($app) {
// Some random version 2 processing here ...
}
我有问题要解决 -
前端总是命中 API 的 v1(通用路由)。我需要根据参数 appversion
的值在内部重定向到 v2。
如何在不向客户端发回 302 重定向 headers 的情况下在 slim 框架路由中执行此操作?基本上,我需要在内部重定向到服务器本身。
注意:我知道 Nginx 和 Apache 重写。让我们把它们放在一边,将范围限制在 slim framework 路由本身。
您需要抽象化您的调用并创建控制器(即您的代码不会那么精简)。
示例:
function doV2() {
// ... do V2 things
}
function doV1() {
// ... do V1 things
}
$app->map(['GET', 'POST'], "/", function (\Slim\Http\Request $request, \Slim\Http\Response $response) use ($app) {
if($app->request()->params('appversion') === 'v2') return doV2();
doV1();
}
$app->map(['GET', 'POST'], "/api/v2", function (\Slim\Http\Request $request, \Slim\Http\Response $response) use ($app) {
doV2();
}
你不能在内部 'redirect' 的原因是你的 'controllers' 是匿名闭包,所以你无法 name/reference/call 它们。相反,如果您将它们抽象为函数(是的,您可能还需要传入 $request/$response),那么您已经命名了可以为适当的路由调用的方法。
除了定义闭包或函数,您还可以定义控制器并在路由器中使用 SlimPHP 的容器解析 - 有一个很好的例子 in the router docs。
最后,您 可以 使用中间件来改变基于您的 appversion 参数发生的事情,具体取决于您想要实现的目标的复杂性。
我会在单个路由定义中使用 optional segments。
use Psr\Http\Message\{
ServerRequestInterface as Request,
ResponseInterface as Response
};
$app->map(['GET', 'POST'], '/[{v2:api/v2}]', function (Request $request, Response $response, array $args) {
if (isset($args['v2'])) { // You may also check $request->getAttribute('appversion')
// Version 2 processing here...
// return $response;
}
// Version 1 processing here...
// return $response;
});
你想要实现的在技术上是可行的,但对我来说,你的问题背后的原因似乎是你想引入你的 API 的新版本,但你不想(或者你不能)更新前端调用新版本,相反,你想在后端处理这个。
如果您要根据 appversion
而不是命中的端点来决定需要调用 API 的哪个版本,那么定义 [=12= 的好处是什么? ] 和 v2
个端点?
如果有人呼叫您的 v1
端点,他们需要您的 v1
响应,如果有人需要您的 v2
响应,他们必须呼叫您的 v2
端点。如果您 return 对 v1
和 v2
端点的响应相同,那么您基本上是在更新 v1
端点行为。
无论如何,您想在另一个路由回调中分派另一个路由,这里是一个完整的示例,展示了如何使用 subRequest
:
<?php
require 'vendor/autoload.php';
$app = new \Slim\App;
$app->map(['GET', 'POST'], '/v1', function($request, $response) use ($app) {
// Get the appversion query parameter and make the decision based on its value
$appVersion = $request->getParam('appversion');
if($appVersion == '1.0') {
return $app->subRequest($request->getMethod(), '/v2',
http_build_query($request->getQueryParams()),
$request->getHeaders(),
$request->getCookieParams(),
$request->getBody()->getContents()
);
}
return 'API version: v1, appversion: ' . $appVersion;
});
$app->map(['GET', 'POST'], '/v2', function($request, $response) {
return 'API version: v2, request method: ' . $request->getMethod() .', appversion: '. $request->getParam('appversion') . ', body: <pre>' . print_r($request->getParsedBody(), 1);
});
$app->get('/form', function() {
return <<<form
<form method="POST" action="/v1?appversion=1.0">
<input type="text" name="foo" value="bar">
<button type="submit" value="submit">Submit</button>
</form>
form;
});
$app->run();
现在,如果您尝试达到 /v1?appversion=1.0
,来自 /v2
回调的响应将被 returned。尝试达到 /v1
且 appversion
等于任何其他值(例如 /v1?appversion=2.0
)会导致应用程序 return v1
响应。
subRequest
方法也可以处理 POST
请求。请参考method documentation in Slim code repository。该示例提供了一个 /form
URI 来证明这一点。
我有一条如下所示的通用路线 -
$app->map(['GET', 'POST'], "/", function (\Slim\Http\Request $request, \Slim\Http\Response $response) use ($app) {
// Some random version 1 processing here ...
}
我有一个 v2 版本,如下所示 -
$app->map(['GET', 'POST'], "/api/v2", function (\Slim\Http\Request $request, \Slim\Http\Response $response) use ($app) {
// Some random version 2 processing here ...
}
我有问题要解决 -
前端总是命中 API 的 v1(通用路由)。我需要根据参数 appversion
的值在内部重定向到 v2。
如何在不向客户端发回 302 重定向 headers 的情况下在 slim 框架路由中执行此操作?基本上,我需要在内部重定向到服务器本身。
注意:我知道 Nginx 和 Apache 重写。让我们把它们放在一边,将范围限制在 slim framework 路由本身。
您需要抽象化您的调用并创建控制器(即您的代码不会那么精简)。
示例:
function doV2() {
// ... do V2 things
}
function doV1() {
// ... do V1 things
}
$app->map(['GET', 'POST'], "/", function (\Slim\Http\Request $request, \Slim\Http\Response $response) use ($app) {
if($app->request()->params('appversion') === 'v2') return doV2();
doV1();
}
$app->map(['GET', 'POST'], "/api/v2", function (\Slim\Http\Request $request, \Slim\Http\Response $response) use ($app) {
doV2();
}
你不能在内部 'redirect' 的原因是你的 'controllers' 是匿名闭包,所以你无法 name/reference/call 它们。相反,如果您将它们抽象为函数(是的,您可能还需要传入 $request/$response),那么您已经命名了可以为适当的路由调用的方法。
除了定义闭包或函数,您还可以定义控制器并在路由器中使用 SlimPHP 的容器解析 - 有一个很好的例子 in the router docs。
最后,您 可以 使用中间件来改变基于您的 appversion 参数发生的事情,具体取决于您想要实现的目标的复杂性。
我会在单个路由定义中使用 optional segments。
use Psr\Http\Message\{
ServerRequestInterface as Request,
ResponseInterface as Response
};
$app->map(['GET', 'POST'], '/[{v2:api/v2}]', function (Request $request, Response $response, array $args) {
if (isset($args['v2'])) { // You may also check $request->getAttribute('appversion')
// Version 2 processing here...
// return $response;
}
// Version 1 processing here...
// return $response;
});
你想要实现的在技术上是可行的,但对我来说,你的问题背后的原因似乎是你想引入你的 API 的新版本,但你不想(或者你不能)更新前端调用新版本,相反,你想在后端处理这个。
如果您要根据 appversion
而不是命中的端点来决定需要调用 API 的哪个版本,那么定义 [=12= 的好处是什么? ] 和 v2
个端点?
如果有人呼叫您的 v1
端点,他们需要您的 v1
响应,如果有人需要您的 v2
响应,他们必须呼叫您的 v2
端点。如果您 return 对 v1
和 v2
端点的响应相同,那么您基本上是在更新 v1
端点行为。
无论如何,您想在另一个路由回调中分派另一个路由,这里是一个完整的示例,展示了如何使用 subRequest
:
<?php
require 'vendor/autoload.php';
$app = new \Slim\App;
$app->map(['GET', 'POST'], '/v1', function($request, $response) use ($app) {
// Get the appversion query parameter and make the decision based on its value
$appVersion = $request->getParam('appversion');
if($appVersion == '1.0') {
return $app->subRequest($request->getMethod(), '/v2',
http_build_query($request->getQueryParams()),
$request->getHeaders(),
$request->getCookieParams(),
$request->getBody()->getContents()
);
}
return 'API version: v1, appversion: ' . $appVersion;
});
$app->map(['GET', 'POST'], '/v2', function($request, $response) {
return 'API version: v2, request method: ' . $request->getMethod() .', appversion: '. $request->getParam('appversion') . ', body: <pre>' . print_r($request->getParsedBody(), 1);
});
$app->get('/form', function() {
return <<<form
<form method="POST" action="/v1?appversion=1.0">
<input type="text" name="foo" value="bar">
<button type="submit" value="submit">Submit</button>
</form>
form;
});
$app->run();
现在,如果您尝试达到 /v1?appversion=1.0
,来自 /v2
回调的响应将被 returned。尝试达到 /v1
且 appversion
等于任何其他值(例如 /v1?appversion=2.0
)会导致应用程序 return v1
响应。
subRequest
方法也可以处理 POST
请求。请参考method documentation in Slim code repository。该示例提供了一个 /form
URI 来证明这一点。