Задний план:
Я пишу RESTful API на symfony. Я хочу, чтобы клиент мог отправлять сообщения на URL-адрес с помощью приложения типа контента / json и публиковать json-объект формы, который ищет действие контроллера.
Я использую довольно базовую настройку контроллера для этого. Давайте предположим для демонстрационных целей, что я пытаюсь аутентифицировать простую комбинацию паролей имени пользователя.
public function loginAction( Request $request ) { $user = new ApiUser(); $form = $this->createForm(new ApiUserType(), $user); if ( "POST" == $request->getMethod() ) { $form->bindRequest($request); if ( $form->isValid() ) { $em = $this->getDoctrine()->getEntityManager(); $repo = $this->getDoctrine()->getRepository('ApiBundle:ApiUser'); $userData = $repo->findOneByUsername($user->getUsername()); if ( is_object($userData) ) { /** do stuff for authenticating **/ } else{ return new Response(json_encode(array('error'=>'no user by that username found'))); } else{ return new Response(json_encode(array('error'=>'invalid form'))); } } }
Теперь проблема, которая у меня есть, и я попробовал var_dumping это до тех пор, пока корова не вернется домой, это то, что когда-либо причина, по которой Symfony не хочет использовать контент-тело application / json и использовать эти данные для заполнения данных формы.
Имя формы: api_apiuser
Поля: имя пользователя, пароль
Каким будет лучший способ справиться с этим типом задачи. Я открыт для предложений, пока я могу заставить это работать. Спасибо за ваше время с этим вопросом.
Вам нужно получить доступ к телу запроса RAW, а затем использовать json_decode. Вероятно, вам придется изменить метод bindRequest
на следующее:
public function bindRequest(Request $request) { if($request->getFormat() == 'json') { $data = json_decode($request->getContent()); return $this->bind($data); } else { // your standard logic for pulling data form a Request object return parent::bind($request); } }
Я действительно не испортил SF2, но это больше угадывает на основе API, exp. с sf1.x и вещами, полученными от презентаций на фреймворке. Возможно, было бы лучше сделать совершенно другой метод, например bindJsonRequest
чтобы вещи были немного более аккуратны.
Ive на самом деле нашел аналогичный способ исправить это, ПОСЛЕ проверки того, является ли метод post и до привязки запроса к форме, я делаю это:
if ( "POST" === $request->getMethod() ) { if (0 === strpos($request->headers->get('Content-Type'), 'application/json')){ $data = json_decode($request->getContent(), true); $request->request->replace(is_array($data) ? $data : array()); } $form->bindRequest($request); /** Rest of logic **/ }
Да, то, что ждет форма во время привязки, представляет собой массив, содержащий ключи, соответствующие вашим свойствам ApiUser.
Поэтому, если вы отправляете запрос POST со строкой:
{ username: 'user', password: 'pass' }
Вам придется преобразовать его в массив с помощью json_decode
например:
$data = json_decode($request->getContent()); // $request->request->get('json_param_name');
Затем вы привязываете этот массив к форме с помощью $form->bind($data);
Форма обновит ваши свойства ApiUser, соответствующие ключам массива (имя пользователя, пароль).
Если вы создаете RESTful json api, я бы посоветовал вам автоматизировать этот процесс с помощью сериализаторов / трансформаторов, например https://github.com/schmittjoh/JMSSerializerBundle/blob/master/Resources/doc/index.rst