Манипулирование данными поста для работы с формами Symfony2 при использовании в API REST
Вопрос
Фон:
Я пишу спокойный API на Symfony. Я хочу, чтобы клиент имел возможность публиковать URL -адрес, используя приложение типа контента/JSON и разместил объект JSON Form, который ищет действие контроллера.
Я использую довольно базовую настройку контроллера для этого. Предположим, что в демонстрационных целях я пытаюсь аутентифицировать простой комбинированную комбинацию пароля пользователя.
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 не хочет принимать приложение/JSON Content-Body и использовать эти данные для заполнения данных формы.
Имя формы: API_APIUSER
Поля: имя пользователя, пароль
Что будет лучшим способом выполнения этого типа задачи. Я открыт для предложений, пока я могу работать. Спасибо за ваше время с этим вопросом.
Решение 2
Я на самом деле нашел аналогичный способ исправить это, после проверки, является ли метод, и перед тем, как привязать запрос с формой, я делаю это:
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 **/
}
Другие советы
Вам нужно получить доступ к корпусу запроса 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
Так что все немного более аккуратно.
Да, то, чего ждет форма во время привязки, - это массив, содержащий ключи, которые соответствуют вашим свойствам Apiuser.
Так что, если вы отправляете запрос сообщения со строкой:
{ 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