Я пытаюсь настроить проект для API с использованием Slim Framework версии 3, я не знаю, кто сделал PSR-7 и пометил объект ответа как неизменный, я не вижу в этом смысла (ИМХО. Пожалуйста, объясните мне если я не прав). Все было намного проще, когда он был худым 2. Теперь я вернулся, чтобы похудеть после долгого времени.
У меня есть маршрут, который является методом post, я получаю данные и сохраняю их в базе данных, и я пытаюсь отправить 201 в качестве кода ответа. все примеры и документация показывают вам, как вы можете изменить код ответа в самом файле index.php, но я пытаюсь заменить его на построитель ответов, который я пытался использовать с фабричным шаблоном для предоставления разных ответов. Проблема в том, что код ответа всегда равен 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;
}
}
Может кто-то указать мне верное направление?
Решение PSR-7 об использовании неизменяемых объектов для Запроса и Ответа задокументировано в Зачем ценить объекты? раздел мета-документа.
С Slim 3 вы всегда должны вернуть 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
Метод также должен вернуть $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;
}
}
Наконец, рассмотрим РКА-Content-Type-рендерер вместо JsonBuilder
Хотя, возможно, это делает больше, чем вы показали.
Обновить:
В идеале вы должны использовать инжектор конструктора для внедрения модели User в контроллер. Сделать это:
Обновите свой контроллер:
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);
};
Других решений пока нет …