我有一个通用的路线如下-
$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 (泛型路由)。我需要根据参数v2 __的值在内部重定向到appversion
。
如何在不向客户端发出302重定向头的情况下,在瘦框架路由中做到这一点?基本上,我需要在内部重定向到服务器本身。
注意:我知道和重写。让我们把它们放在一边,把范围限制在仅局限于纤细的框架路由上。
发布于 2019-12-01 23:52:22
您想要实现的在技术上是可能的,但在我看来,您的问题背后的原因似乎是您希望引入API的新版本,但是您不想(或者不能)更新前端以调用新版本,而是希望在后端处理这个问题。
如果要根据appversion
而不是命中的端点来决定需要调用哪个版本的API,那么定义v1
和v2
端点有什么好处呢?
如果有人调用您的v1
端点,他们需要您的v1
响应,如果有人需要您的v2
响应,则必须调用您的v2
端点。如果您为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
回调的响应。试图使用等于任何其他值(例如,/v1
)的appversion
到达appversion
,将导致应用程序返回v1
响应。
subRequest
方法还能够处理POST
请求。请参考Slim代码库中的方法文档。该示例提供了一个/form
URI来演示这一点。
发布于 2019-11-30 00:58:22
我会在一个路由定义中使用可选段来完成这个任务。
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;
});
发布于 2019-11-29 23:45:30
您需要抽象调用并创建控制器(也就是说,您的代码不会那么苗条)。
示例:
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();
}
您不能在内部“重定向”的原因是您的“控制器”是匿名闭包,因此您无法命名/引用/调用它们。相反,如果将它们抽象成函数(是的,您可能也需要传入$request/$response ),那么您已经为适当的路由指定了方法。
除了定义闭包或函数之外,您还可以定义控制器,并在路由器中使用SlimPHP的容器解决方案--这是一个很好的示例在路由器文档中。
最后,您可能需要使用中间件来根据应用程序参数更改所发生的事情,这取决于您想要实现的目标的复杂性。
https://stackoverflow.com/questions/59114173
复制