在使用 slimframework 的不可变响应时遇到问题
having trouble with slimframework's Immutable responses
我正在尝试使用 slim 框架版本 3 为 API 设置一个项目,我不知道是谁制作了 PSR-7 并将响应对象标记为不可变的,我没有看到任何在那使用(恕我直言。如果我错了请解释)。苗条的时候就轻松多了2。好久好久回来苗条了。
我有一个路由,它是一个 post 方法,我正在获取数据并将其保存到数据库中,我正在尝试发送 201 作为响应代码。所有示例和文档都向您展示了如何更改 index.php 文件本身中的响应代码,但我试图从响应构建器中更改它,我尝试使用工厂模式来提供不同的响应.问题是无论我从响应生成器 class 调用什么函数,响应代码总是保持 200。我尝试了很多论坛和不同的苗条方式,但仍然无法解决这个问题。我几乎决定放弃 PSR 7 路由器实施,转而实施我自己的路由解决方案。但我记得不要重新发明轮子,所以我来到这里作为最后的尝试。下面是代码。
路由定义
$app->post('/users', function(ServerRequestInterface $req, ResponseInterface $res) {
$data = $req->getParsedBody();
$model = new \Apex\Models\User(ApexDB::getInstance());
$jsonBuilder = ApexResponse::getBuilder('JSON', $res);
$control = new \Apex\Controllers\User($model, $jsonBuilder);
$control->create($data);
});
控制器方法(抽象我只是设置它)
public function create($data) {
if($this->model->save($data)) {
$this->response->build($data,201);
} else {
$this->response->build('error',400);
}
}
JSON 建设者
class JSONBuilder implements Response
{
public $response;
public function __construct($response)
{
$this->response = $response;
}
public function build($data, $status)
{
$response = $this->response->withJSON($data,$status);
return $response;
}
}
谁能指出我正确的方向?
元文档的 Why value objects? 部分记录了 PSR-7 对请求和响应使用不可变对象的决定。
对于 Slim 3,您必须始终 return 来自控制器方法的 Response
实例。
$app->post('/users', function(ServerRequestInterface $req, ResponseInterface $res) {
$data = $req->getParsedBody();
$model = new \Apex\Models\User(ApexDB::getInstance());
$jsonBuilder = ApexResponse::getBuilder('JSON', $res);
$control = new \Apex\Controllers\User($model, $jsonBuilder);
return $control->create($data);
});
然后您的 create
方法还需要 return $response
:
public function create($data) {
if($this->model->save($data)) {
$this->response->build($data,201);
} else {
$this->response->build('error',400);
}
return $this->response;
}
然后它应该可以工作了。
但是,您可以直接从路由声明中使用控制器方法,而无需闭包:
$app->post('/users', `Apex\Controllers\User::create`);
控制器的 create
方法将如下所示:
namespace Apex\Controllers;
class User
{
public function create($request, $response)
{
$data = $request->getParsedBody();
$model = new \Apex\Models\User(ApexDB::getInstance());
$jsonBuilder = ApexResponse::getBuilder('JSON', $response);
if ($model->save($data)) {
$response = $jsonBuilder->build($data, 201);
} else {
$response = $jsonBuilder->build('error', 400);
}
return $response;
}
}
最后,考虑 rka-content-type-renderer 而不是 JsonBuilder
,尽管它可能比您展示的更多。
更新:
理想情况下,您将使用构造函数注入将用户模型注入控制器。为此:
更新您的控制器:
namespace Apex\Controllers;
use Apex\Models\User as UserModel;
class User
{
protected $userModel;
public function __construct(UserModel $userModel)
{
$this->userModel = $userModel;
}
public function create($request, $response)
{
$data = $request->getParsedBody();
$jsonBuilder = ApexResponse::getBuilder('JSON', $response);
if ($this->userModel->save($data)) {
$response = $jsonBuilder->build($data, 201);
} else {
$response = $jsonBuilder->build('error', 400);
}
return $response;
}
}
为 Pimple 依赖注入容器编写一个工厂:
$container = $app->getContainer();
$container['Apex\Controllers\User'] = function ($c) {
$userModel = new \Apex\Models\User(ApexDB::getInstance());
return new \ApexController\User($userModel);
};
我正在尝试使用 slim 框架版本 3 为 API 设置一个项目,我不知道是谁制作了 PSR-7 并将响应对象标记为不可变的,我没有看到任何在那使用(恕我直言。如果我错了请解释)。苗条的时候就轻松多了2。好久好久回来苗条了。
我有一个路由,它是一个 post 方法,我正在获取数据并将其保存到数据库中,我正在尝试发送 201 作为响应代码。所有示例和文档都向您展示了如何更改 index.php 文件本身中的响应代码,但我试图从响应构建器中更改它,我尝试使用工厂模式来提供不同的响应.问题是无论我从响应生成器 class 调用什么函数,响应代码总是保持 200。我尝试了很多论坛和不同的苗条方式,但仍然无法解决这个问题。我几乎决定放弃 PSR 7 路由器实施,转而实施我自己的路由解决方案。但我记得不要重新发明轮子,所以我来到这里作为最后的尝试。下面是代码。
路由定义
$app->post('/users', function(ServerRequestInterface $req, ResponseInterface $res) {
$data = $req->getParsedBody();
$model = new \Apex\Models\User(ApexDB::getInstance());
$jsonBuilder = ApexResponse::getBuilder('JSON', $res);
$control = new \Apex\Controllers\User($model, $jsonBuilder);
$control->create($data);
});
控制器方法(抽象我只是设置它)
public function create($data) {
if($this->model->save($data)) {
$this->response->build($data,201);
} else {
$this->response->build('error',400);
}
}
JSON 建设者
class JSONBuilder implements Response
{
public $response;
public function __construct($response)
{
$this->response = $response;
}
public function build($data, $status)
{
$response = $this->response->withJSON($data,$status);
return $response;
}
}
谁能指出我正确的方向?
元文档的 Why value objects? 部分记录了 PSR-7 对请求和响应使用不可变对象的决定。
对于 Slim 3,您必须始终 return 来自控制器方法的 Response
实例。
$app->post('/users', function(ServerRequestInterface $req, ResponseInterface $res) {
$data = $req->getParsedBody();
$model = new \Apex\Models\User(ApexDB::getInstance());
$jsonBuilder = ApexResponse::getBuilder('JSON', $res);
$control = new \Apex\Controllers\User($model, $jsonBuilder);
return $control->create($data);
});
然后您的 create
方法还需要 return $response
:
public function create($data) {
if($this->model->save($data)) {
$this->response->build($data,201);
} else {
$this->response->build('error',400);
}
return $this->response;
}
然后它应该可以工作了。
但是,您可以直接从路由声明中使用控制器方法,而无需闭包:
$app->post('/users', `Apex\Controllers\User::create`);
控制器的 create
方法将如下所示:
namespace Apex\Controllers;
class User
{
public function create($request, $response)
{
$data = $request->getParsedBody();
$model = new \Apex\Models\User(ApexDB::getInstance());
$jsonBuilder = ApexResponse::getBuilder('JSON', $response);
if ($model->save($data)) {
$response = $jsonBuilder->build($data, 201);
} else {
$response = $jsonBuilder->build('error', 400);
}
return $response;
}
}
最后,考虑 rka-content-type-renderer 而不是 JsonBuilder
,尽管它可能比您展示的更多。
更新:
理想情况下,您将使用构造函数注入将用户模型注入控制器。为此:
更新您的控制器:
namespace Apex\Controllers; use Apex\Models\User as UserModel; class User { protected $userModel; public function __construct(UserModel $userModel) { $this->userModel = $userModel; } public function create($request, $response) { $data = $request->getParsedBody(); $jsonBuilder = ApexResponse::getBuilder('JSON', $response); if ($this->userModel->save($data)) { $response = $jsonBuilder->build($data, 201); } else { $response = $jsonBuilder->build('error', 400); } return $response; } }
为 Pimple 依赖注入容器编写一个工厂:
$container = $app->getContainer(); $container['Apex\Controllers\User'] = function ($c) { $userModel = new \Apex\Models\User(ApexDB::getInstance()); return new \ApexController\User($userModel); };