IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Symfony PHP Discussion :

Consommer une API avec HttpClient


Sujet :

Symfony PHP

  1. #1
    Candidat au Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2021
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2021
    Messages : 3
    Par défaut Consommer une API avec HttpClient
    Bonjour à tous,

    Je tiens à préciser que je débute sous symfony.
    Je souhaite consommer une API via cette adresse : "http://ergast.com/api/f1/current/driverStandings". (tester avec Insomnia)

    J'obtiens cette erreur:
    Return value of App\Service\CallApiService::getResult() must be an instance of Symfony\Component\HttpFoundation\Response, instance of Symfony\Component\HttpClient\Response\TraceableResponse returned
    Avez-vous une idée, j'ai essayé beaucoup de choses. J'ai aussi essayé de return un tableau.
    Un grand merci par avance, bonne journée

    Voici mon ApiService et mon Controller:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?php
     
    namespace App\Service;
     
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Contracts\HttpClient\HttpClientInterface;
     
    class CallApiService
    {
        private $client;
     
        public function __construct(HttpClientInterface $client)
        {
            $this->client = $client;
        }
     
        public function getResult(): Response
     
        {
            $response = $this->client->request(
                'GET',
                'http://ergast.com/api/f1/current/driverStandings',
            );
            return $response;
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <?php
     
    namespace App\Controller;
     
    use App\Service\CallApiService;
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Routing\Annotation\Route;
     
    class HomeController extends AbstractController
    {
        /**
         * @Route("/home", name="home")
         */
        public function index(CallApiService $callApiService): Response
        {
            dd($callApiService->getResult());
     
            return $this->json($callApiService->getResult(), 200, [], 
            );
     
        }
    }

  2. #2
    Expert confirmé

    Avatar de -Nikopol-
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2013
    Messages
    2 174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2013
    Messages : 2 174
    Billets dans le blog
    5
    Par défaut
    Bonjour,
    public function getResult(): Response ici tu dis à symfony qu'il doit renvoyer une Response de la classe HttpFoundation\Response; puisque tu envoyes le retour de ton appel à l'api, ça couine. renvoie simplement le contenu du retour de l'api dans un premier temps(il faudra envisager un try catch après)
    Ensuite l'url que tu interroges renvoie une image. je doute que ce soit ca que tu recherches. il faut rajouter l'extension .json ou .xml : http://ergast.com/api/f1/2008/driverStandings.jsondonc, ton service :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?php
     
    namespace App\Service;
     
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Contracts\HttpClient\HttpClientInterface;
     
    class CallApiService
    {
        private $client;
     
        public function __construct(HttpClientInterface $client)
        {
            $this->client = $client;
        }
     
        public function getResult()// pas response ici
     
        {
            $response = $this->client->request(
                'GET',
                'http://ergast.com/api/f1/current/driverStandings',
            );
            return $response->getContent();
        }
    }
    le contrôleur qui etend abstractController lui doit renvoyer une Response. et pas besoin de transformer en json puisque tu reçoit deja un json.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <?php
     
    namespace App\Controller;
     
    use App\Service\CallApiService;
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Routing\Annotation\Route;
     
    class HomeController extends AbstractController
    {
        /**
         * @Route("/home", name="home")
         */
        public function index(CallApiService $callApiService): Response
        {
            $standing = $callApiService->getResult();
     
            return new Response($result);
     
        }
    }

  3. #3
    Candidat au Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2021
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2021
    Messages : 3
    Par défaut
    Super merci beaucoup, ça marche bien. Je suis content d'avoir saisi le truc ^^

    Autre petite question, je n'arrive pas à parcourir le tableau json comme je veux. Je m'explique : Je voudrais obtenir via une boucle for la position et le nom du pilote dans une vue twig. Je vous partage le json et le code dans mon twig.
    Merci à vous !

    Code twig : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    {% for MRDATA in StandingsLists as DriverStandings%}
    					<div class="col">
    						<div class="card shadow-lg h-100 m-2">
                               echo DriverStandings->position; 
                                    DriverStandings->givenName;
    						</div>
    					</div>
    {% endfor %}

    JSON:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    {
      "MRData": {
        "xmlns": "http:\/\/ergast.com\/mrd\/1.4",
        "series": "f1",
        "url": "http://ergast.com/api/f1/current/driverstandings.json",
        "limit": "30",
        "offset": "0",
        "total": "21",
        "StandingsTable": {
          "season": "2021",
          "StandingsLists": [
            {
              "season": "2021",
              "round": "21",
              "DriverStandings": [
                {
                  "position": "1",
                  "positionText": "1",
                  "points": "369.5",
                  "wins": "9",
                  "Driver": {
                    "driverId": "max_verstappen",
                    "permanentNumber": "33",
                    "code": "VER",
                    "url": "http:\/\/en.wikipedia.org\/wiki\/Max_Verstappen",
                    "givenName": "Max",
                    "familyName": "Verstappen",
                    "dateOfBirth": "1997-09-30",
                    "nationality": "Dutch"
                  },
                  "Constructors": [
                    {
                      "constructorId": "red_bull",
                      "url": "http:\/\/en.wikipedia.org\/wiki\/Red_Bull_Racing",
                      "name": "Red Bull",
                      "nationality": "Austrian"
                    }
                  ]
                },
                {
                  "position": "2",
                  "positionText": "2",
                  "points": "369.5",
                  "wins": "8",
                  "Driver": {
                    "driverId": "hamilton",
                    "permanentNumber": "44",
                    "code": "HAM",
                    "url": "http:\/\/en.wikipedia.org\/wiki\/Lewis_Hamilton",
                    "givenName": "Lewis",
                    "familyName": "Hamilton",
                    "dateOfBirth": "1985-01-07",
                    "nationality": "British"
                  },
                  "Constructors": [
                    {
                      "constructorId": "mercedes",
                      "url": "http:\/\/en.wikipedia.org\/wiki\/Mercedes-Benz_in_Formula_One",
                      "name": "Mercedes",
                      "nationality": "German"
                    }
                  ]
                },

  4. #4
    Expert confirmé

    Avatar de -Nikopol-
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2013
    Messages
    2 174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2013
    Messages : 2 174
    Billets dans le blog
    5
    Par défaut
    twig est un moteur de template php donc il faut que tu lui passe un array php. Ton controller devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
         * @Route("/home", name="home")
         */
        public function index(): Response
        {
            $result = $this->getResult();
            $result = json_decode($result,true);
            return $this->render('home/index.html.twig', [
                'standing' => $result
            ]);
        }
    et dans twig (je te conseille d'aller lire la doc qui est très bien faite) pas de echo ni de "->"
    ca donnerait le fichier suivant dans template/home/index.html.twig
    Code twig : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    {% extends 'base.html.twig' %}
     
    {% block title %}F1{% endblock %}
     
    {% block body %}
        <style>
            .example-wrapper {
                margin: 1em auto;
                max-width: 80%;
                width: 95%;
                font: 18px/1.5 sans-serif;
            }
     
            ul {
                list-style-type: none;
            }
     
            .example-wrapper code {
                background: #F5F5F5;
                padding: 2px 6px;
            }
        </style>
     
        <div class="example-wrapper">
            {% set DriverStandings = standing['MRData']['StandingsTable']['StandingsLists'][0]['DriverStandings'] %}
            <div>sport : {{ standing['MRData']['series'] }}</div>
            <div>saison : {{ standing['MRData']['StandingsTable']['season'] }}</div>
            <ul>
            {% for driver in DriverStandings %}
             <li>{{ driver['Driver']['familyName'] }}</li>
            {% endfor %}
            </ul>
     
            {{ dump(standing) }}
            {{ dump(DriverStandings) }}
        </div>
    {% endblock %}

  5. #5
    Candidat au Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2021
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2021
    Messages : 3
    Par défaut
    Merci pour cette réponse clair et détaillée.

    Il me reste un petit soucis pour conclure ce test.

    J'ai cette erreur :
    Attempted to call an undefined method named "getResult" of class "App\Controller\HomeController
    L'appel se fait, je ne comprends pas pourquoi il ne veut pas de mon GetResult

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?php
     
    namespace App\Controller;
     
    use App\Service\CallApiService;
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Routing\Annotation\Route;
     
    class HomeController extends AbstractController
    {
        /** 
        * @Route("/home", name="home")
        */
        public function index(CallApiService $callApiService): Response
        {
            $result = $this->getResult();
            $result = json_decode($result,true);
     
            return $this->render('home/index.html.twig', [
                'standing' => $result
            ]);
        }
    }

  6. #6
    Expert confirmé

    Avatar de -Nikopol-
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2013
    Messages
    2 174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2013
    Messages : 2 174
    Billets dans le blog
    5
    Par défaut
    Ma faute, pour tester le rendu avec twig j'ai copié la fonction du getResult() directement dans mon controller (ce qu'il ne faut pas faire) d'ou le $this puisqu'on est dans la meme classe. Il suffit de garder l'injection de dépendance et remplacer $this par $callApiService

Discussions similaires

  1. Peut-on faire une API avec Delphi ?
    Par WebPac dans le forum API, COM et SDKs
    Réponses: 14
    Dernier message: 11/04/2023, 14h48
  2. Accéder à un fichier CSV via une API avec AJAX
    Par sonica dans le forum AJAX
    Réponses: 7
    Dernier message: 24/07/2016, 13h56
  3. creer une API avec c++ sous Codeblocks
    Par khenissi dans le forum Code::Blocks
    Réponses: 1
    Dernier message: 08/08/2010, 12h53
  4. Développer une API avec Java
    Par aubou dans le forum Débuter avec Java
    Réponses: 12
    Dernier message: 15/07/2009, 07h47
  5. Probléme: un client java qui consomme une array avec soap
    Par mejdi331 dans le forum Services Web
    Réponses: 1
    Dernier message: 28/01/2009, 16h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo