Comment puis-je envoyer une réponse JSON dans le contrôleur symfony2


90

J'utilise jQuerypour modifier mon formulaire intégré Symfony.

J'affiche le formulaire dans une jQueryboîte de dialogue, puis je le soumets.

Les données entrent correctement dans la base de données.

Mais je ne sais pas si je dois envoyer un certain JSONretour à jQuery. En fait, je suis un peu confus avec les JSONchoses.

Supposons que j'ai ajouté une ligne dans ma table avec `` jQuery et que lorsque je soumets le formulaire, une fois les données soumises, je souhaite renvoyer ces données de ligne afin que je puisse ajouter dynamiquement la ligne de table pour afficher les données ajoutées.

Je ne sais pas comment récupérer ces données.

Ceci est mon code actuel:

$editForm = $this->createForm(new StepsType(), $entity);

$request = $this->getRequest();

$editForm->bindRequest($request);

if ($editForm->isValid()) {
    $em->persist($entity);
    $em->flush();

    return $this->render('::success.html.twig');               
}

Ceci est juste le modèle avec le message de réussite.

Réponses:


187

Symfony 2.1

$response = new Response(json_encode(array('name' => $name)));
$response->headers->set('Content-Type', 'application/json');

return $response;

Symfony 2.2 et supérieur

Vous avez une classe JsonResponse spéciale , qui sérialise le tableau en JSON:

return new JsonResponse(array('name' => $name));

Mais si votre problème est de savoir comment sérialiser l'entité, vous devriez jeter un œil à JMSSerializerBundle

En supposant que vous l'avez installé, vous devrez simplement faire

$serializedEntity = $this->container->get('serializer')->serialize($entity, 'json');

return new Response($serializedEntity);

Vous devriez également rechercher des problèmes similaires sur StackOverflow:


1
Alors, comment sérialiser l'entité ET l'envoyer en tant que réponse JSON? Je cherche ça depuis une semaine .. stackoverflow.com/questions/14798532/…
George Katsanos

Vous pouvez également utiliser symfony JsonResponse (Symfony \ Component \ HttpFoundation \ JsonResponse)
Kiddo

5
Il est préférable de définir l'en-tête de type de contenu return new Response ($ serializedEntity, 200, array ('Content-Type' => 'application / json'));
Sergii Smirnov

La suggestion de Sergii est la meilleure (du moins pour moi), si je ne règle pas le Content-Type, sur le client je recevrai un content-type text / html. Si j'utilise JsonResponse, pour une raison étrange, j'obtiens une seule chaîne avec le contenu à l'intérieur
LuisF

56

Symfony 2.1 a une classe JsonResponse .

return new JsonResponse(array('name' => $name));

Le tableau transmis sera encodé en JSON, le code d'état par défaut sera 200 et le type de contenu sera défini sur application / json.

Il existe également une setCallbackfonction pratique pour JSONP.


16

Depuis Symfony 3.1, vous pouvez utiliser JSON Helper http://symfony.com/doc/current/book/controller.html#json-helper

public function indexAction()
{
// returns '{"username":"jane.doe"}' and sets the proper Content-Type header
return $this->json(array('username' => 'jane.doe'));

// the shortcut defines three optional arguments
// return $this->json($data, $status = 200, $headers = array(), $context = array());
}

10

Pour compléter la réponse @thecatontheflat, je recommanderais également d'envelopper votre action dans un try … catchbloc. Cela empêchera votre point de terminaison JSON de se rompre sur les exceptions. Voici le squelette que j'utilise:

public function someAction()
{
    try {

        // Your logic here...

        return new JsonResponse([
            'success' => true,
            'data'    => [] // Your data here
        ]);

    } catch (\Exception $exception) {

        return new JsonResponse([
            'success' => false,
            'code'    => $exception->getCode(),
            'message' => $exception->getMessage(),
        ]);

    }
}

De cette façon, votre point de terminaison se comportera de manière cohérente même en cas d'erreurs et vous pourrez les traiter directement du côté client.


8

Si vos données sont déjà sérialisées:

a) envoyer une réponse JSON

public function someAction()
{
    $response = new Response();
    $response->setContent(file_get_contents('path/to/file'));
    $response->headers->set('Content-Type', 'application/json');
    return $response;
}

b) envoyer une réponse JSONP (avec rappel)

public function someAction()
{
    $response = new Response();
    $response->setContent('/**/FUNCTION_CALLBACK_NAME(' . file_get_contents('path/to/file') . ');');
    $response->headers->set('Content-Type', 'text/javascript');
    return $response;
}

Si vos données doivent être sérialisées:

c) envoyer une réponse JSON

public function someAction()
{
    $response = new JsonResponse();
    $response->setData([some array]);
    return $response;
}

d) envoyer une réponse JSONP (avec rappel)

public function someAction()
{
    $response = new JsonResponse();
    $response->setData([some array]);
    $response->setCallback('FUNCTION_CALLBACK_NAME');
    return $response;
}

e) utiliser des groupes dans Symfony 3.xx

Créez des groupes dans vos entités

<?php

namespace Mindlahus;

use Symfony\Component\Serializer\Annotation\Groups;

/**
 * Some Super Class Name
 *
 * @ORM    able("table_name")
 * @ORM\Entity(repositoryClass="SomeSuperClassNameRepository")
 * @UniqueEntity(
 *  fields={"foo", "boo"},
 *  ignoreNull=false
 * )
 */
class SomeSuperClassName
{
    /**
     * @Groups({"group1", "group2"})
     */
    public $foo;
    /**
     * @Groups({"group1"})
     */
    public $date;

    /**
     * @Groups({"group3"})
     */
    public function getBar() // is* methods are also supported
    {
        return $this->bar;
    }

    // ...
}

Normaliser votre objet Doctrine dans la logique de votre application

<?php

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
// For annotations
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;

...

$repository = $this->getDoctrine()->getRepository('Mindlahus:SomeSuperClassName');
$SomeSuperObject = $repository->findOneById($id);

$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$encoder = new JsonEncoder();
$normalizer = new ObjectNormalizer($classMetadataFactory);
$callback = function ($dateTime) {
    return $dateTime instanceof \DateTime
        ? $dateTime->format('m-d-Y')
        : '';
};
$normalizer->setCallbacks(array('date' => $callback));
$serializer = new Serializer(array($normalizer), array($encoder));
$data = $serializer->normalize($SomeSuperObject, null, array('groups' => array('group1')));

$response = new Response();
$response->setContent($serializer->serialize($data, 'json'));
$response->headers->set('Content-Type', 'application/json');
return $response;
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.