2016-11-13 2 views
0

Я пытаюсь настроить проект для API с использованием slim framework версии 3, я не знаю, кто создал PSR-7 и поместил объект ответа как неизменный, я не вижу никаких используйте в этом (ИМХО, пожалуйста, объясните мне, если я ошибаюсь). Все было намного легче, когда было тонким. Теперь я вернулся в строй после долгого времени., имеющий проблемы с неизменяемыми ответами slimframework

У меня есть маршрут, который является методом 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; 
    } 
} 

может кто-нибудь мне точку в правильном направление?

ответ

1

Решение PSR-7 использовать неизменяемые объекты для запроса и ответа задокументировано в разделе Why value objects? метаданных.

С 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; 
    } 
} 

Наконец, рассмотрите rka-content-type-renderer вместо JsonBuilder, хотя, возможно, он делает больше, чем вы показали.


Update:

В идеале нужно использовать инъекции конструктора, чтобы ввести модель пользователя в контроллер.Для этого:

  1. Обновление контроллера:

    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; 
        } 
    } 
    
  2. Написать завод для контейнера инъекции зависимостей Прыщ:

    $container = $app->getContainer(); 
    $container['Apex\Controllers\User'] = function ($c) { 
        $userModel = new \Apex\Models\User(ApexDB::getInstance()); 
        return new \ApexController\User($userModel); 
    }; 
    
+0

О, вы можете также рассмотреть вопрос о верните «id» сохраненного пользовательского объекта в ответ «201». Также неплохо включить заголовок 'Location', указывающий на конечную точку для этого пользовательского ресурса (/ users /: id) при угадывании. –

+0

спасибо за подробный ответ, не создает ли жесткую связь для создания экземпляров модели внутри контроллера? Я думал, что могу использовать инъекцию конструктора? или контейнер обслуживания? на ваш взгляд, хороший? – Vignesh

+1

Я бы использовал инъекцию конструктора для модели, да. –