Récupérer valeur JSon d'un script php

Bonjour,


 


 


Je suis débutant et j'essaye aujourd'hui de refaire des petits tuto que j'ai vu sur le net. 


J'essaye donc de me connecter à  une BDD mysql et d'afficher les données de ma table dans un UiTextView. 


 


J'ai essayé de refaire le code en faisant un script php qui renvoie du JSon et en essayant de l'utiliser via mon appli, le problème c'est que je n'arrive plus à  lancer mon appli en essayant beaucoup de chose pour récupérer la réponse du script en JSon. 


 


Voici le code que j'utilise : 



NSInteger success = 0;

NSString *post = [[NSString alloc] initWithFormat:@id=%@&;id_categorie=%@&;NumLigne=%@", @1, [NSString stringWithFormat:@%ld,_NumLigne], @1];

NSURL *url=[NSURL URLWithString:@URL_DU_SCRIPT_LOGIN];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:@%lu, (unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:@POST];
[request setValue:postLength forHTTPHeaderField:@Content-Length];
[request setValue:@application/json forHTTPHeaderField:@Accept];
[request setValue:@application/x-www-form-urlencoded forHTTPHeaderField:@Content-Type];
[request setHTTPBody:postData];

NSError *error = nil;
//NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *response = nil;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];


NSDictionary *jsonData = [NSJSONSerialization
JSONObjectWithData:urlData
options:NSJSONReadingMutableContainers
error:&error];

success = [jsonData[@Reponse] integerValue];
NSString *ligne = (NSString *) jsonData[@ligne];


Pourriez m'aider pour voir ce qui ne va pas ? Soyez indulgent je débute et j'essaye juste de refaire les tuto que je vois sur le net avant de me lancer dans la réalisation d'une appli. 


 


 


Merci d'avance pour votre aide.


 


 


 


 


 


Réponses

  • LeChatNoirLeChatNoir Membre, Modérateur

    Alors je t'arrête tout de suite, si tu es débutant, ne démarres pas en Objective-C. Commences par apprendre le swift !


  • Bonjour,


     


    Merci pour ta réponse mais j'essaye d'apprendre également l'objective C pour pouvoir m'enrichir. 


    Ensuite je passerais au swift. 


     


    Est-ce que quelqu'un pourrait m'aider pour mon souci ?


     


    Merci d'avance.

  • LarmeLarme Membre
    janvier 2017 modifié #4

    Ici :   



        NSString *post = [[NSString alloc] initWithFormat:@id=%@&;id_categorie=%@&;NumLigne=%@", @1, [NSString stringWithFormat:@%ld,_NumLigne], @1];

    Tu formates comme du GET tes paramètres POST, c'est bizarre, et c'est moins modifiable, tu ne remarqueras pas une erreur bête comme un caractère en rab.


    Le mieux :



    NSDictionary *parameters = @[;@id:@1, @id_category:@(_NumLigne), @NumLigne:@1] //D'ailleurs, j'pense que tu t'es planté dans l'ordre, c'est bizarre.
    NSError *errorJSON = nil;
    NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:&errorJSON];
    if (errorJSON){NSLog(@Ooops, invalid parameters);}


        NSURL *url=[NSURL URLWithString:@URL_DU_SCRIPT_LOGIN];

    On vire, car c'est fait précédemment, d'ailleurs l'encoding en ASCII ?



    //    NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

       Ceci me semble correct:



    NSString *postLength = [NSString stringWithFormat:@%lu, (unsigned long)[postData length]];
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
        [request setURL:url];
        [request setHTTPMethod:@POST];
        [request setValue:postLength forHTTPHeaderField:@Content-Length];
        [request setValue:@application/json forHTTPHeaderField:@Accept];
        [request setValue:@application/x-www-form-urlencoded forHTTPHeaderField:@Content-Type];
        [request setHTTPBody:postData];


        NSError *error = nil;
        NSHTTPURLResponse *response = nil;
        NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

    On va rajouter : Car on évite de mettre nil dans les paramètres erreurs, mais surtout on les lit quand ça ne marche pas ! ça pourrait aider grandement !



    if (error){NSLog(@Error: %@", error);}

    On va créer une nouvelle erreur pour plus de clarté. C'est pas obligé, mais vu que tu ne les lis pas.



    NSError *errorReponseJSON = nil;
        NSDictionary *jsonData = [NSJSONSerialization
                                  JSONObjectWithData:urlData
                                  options:NSJSONReadingMutableContainers
                                  error:&errorReponseJSON];
       
    if (errorReponseJSON){NSLog(@errorReponseJSON: %@", errorReponseJSON);}

    Euh, c'est sûr que ton JSON est bien un dictionnaire au top level ?



       success = [jsonData[@Reponse] integerValue];
        NSString *ligne = (NSString *) jsonData[@ligne];

    Globalement, il me semble que sendSynchronousRequest:returningResponse:error: est dépréciée.


    Et surtout, c'est synchrone, ça veut dire que ça va bloquer ton thread, et vu qu'en général, c'est le main thread, ça va bloquer ton UI. Il vaut mieux utiliser NSURLSession.


    Après, il y a pleins d'endroits où ça ne pourrait pas marcher, notamment sur les différents NSError que tu ne lis pas. Et sinon, cela peut se passer du côté de la désérialisation, et là , il faudrait transformer ton urlData en NSString (NSString *jsonString = [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding] ;)  et nous montrer sa valeur, c'est peut-être un NSArray at top level (je ne sais plus s'il y a un cast de forcé, où que ça renvoie nil quand tu désérialises avec le mauvais type).


  • CéroceCéroce Membre, Modérateur
    Moi, ce que je ne comprends pas, c'est pourquoi tu fais du POST.
    Si tu cherches à  LIRE les données depuis le serveur et les afficher dans la tableview, alors c'est du GET.

    Quand ça fonctionnera, suit ce que dit Larme, et lance une requête asynchrone avec NSURLSession. (Et attention, on ne met pas à  jour une UITableView sur un thread secondaire, il faudra le faire sur le thread principal).
  • Bonsoir,


     


    Merci Larme pour votre aide. 


    J'ai testé ce que vous m'avez dit, mais ça ne fonctionne pas, la variable success = 0 et la ligne est vide également, quand je l'affiche dans l'UITextView, je vois apparaà®tre "variable(s) non déclarée(s)". Je n'ai aucune erreur dans le terminal.


     


    Je ne sais pas trop pourquoi j'ai aucune valeur.


     


    Effectivement, j'avais inversé les 2 paramètres.


    Pour ce qui est du JSon, le script renvoie :  


     


    Réponse:1 et ligne: "CECI EST MA PREMIERE LIGNE"


     


     


    @Céroce,


     


    Effectivement, j'ai pris un exemple avec un formulaire à  remplir (avant d'envoyer) et là  le POST était plutôt logique, par contre dans mon cas, il est plus logique d'utiliser le GET. 


     


    Merci pour votre aide.

  • Pour ce qui est du JSon, le script renvoie : 


    Réponse:1 et ligne: "CECI EST MA PREMIERE LIGNE"

     



    Que donne NSString *jsonString = [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding]; ?


  • Bonjour,


     


    NSString *jsonString = [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];


     


    Ca renvoie : 


     


      


    {"Réponse":0,"ligne":"Variable(s) non déclarée(s)"}


  • Je pense que l'utilisation de URLComponents et URLQueryItem est recommandé pour éviter les problèmes de construction de requêtes déjà . Et comme l'a dit Larme je pense que URLSession est plus que conseillé dorénavant.


     


    Tu es certains que coté serveur tout est ok ? As-tu essayé de lancer des requêtes via des services comme PostMan pour voir comment réagissait ton serveur ?

  • Bonsoir,


     


    oui côté serveur, ça à  l'air de fonctionner, j'ai testé avec CocoaRestClient et je vois bien le résultat attendu. 


    j'ai essayé (avec un exemple trouvé sur le net) avec URLSession et j'obtiens toujours le même résultat :


     


    {"Réponse":0,"ligne":"Variable(s) non déclarée(s)"}


  • CéroceCéroce Membre, Modérateur
    janvier 2017 modifié #11

    {"Réponse":0,"ligne":"Variable(s) non déclarée(s)"}

    Alors ça va ;-)
    ça indique que
    1) ton serveur répond
    2) qu'il te renvoie bien un JSON
    3) que tu parviens à  le parser

    La question est maintenant pourquoi le serveur te renvoie ça. Magiic te donne deux explications probables:
    1) le script côté serveur n'est pas au point (a priori, tu as éliminé cette piste)
    2) les paramètres sont mal envoyés. Il te conseille d'utiliser NSURLComponents et NSURLQueryItem afin d'éviter ce genre de problèmes.

    Magiic part du principe que tu passes les paramètres dans l'URL et pas en JSON (ce qu'a compris Larme). Personnellement, à  la lecture des messages, je ne sais pas quelle option tu as choisi.
  • Pourrais-tu montrer exactement ce que tu mets avec CocoaRestClient ?


     


     





    Magiic part du principe que tu passes les paramètres dans l'URL et pas en JSON (ce qu'a compris Larme). Personnellement, à  la lecture des messages, je ne sais pas quelle option tu as choisi.




    De ce que j'ai compris, les paramètres POST se mettent dans le HTTPBody et les GET dans l'URL, même si apparemment côté serveur on peu faire un peu ce qu'on veut.


  • Utilise AFNetworking, tu vas vraiment gagner du temps ...


  • Bonsoir,


     


     Apparemment le problème vient du passage des paramètres dans l'URL. 


    En effet si je lance le script sans passer de paramètres, il me renvoie {"Reponse":0,"ligne":"variable(s) non dàƒÂ©claràƒÂ©e(s)"}


    La même chose que ce que je récupère via l'appli. 


     


    En effet dans le script php je teste les paramètres si ils sont renseignés ou non :



    if(!isset($_POST['id']) || !isset($_POST['id_categorie']) || !isset($_POST['NumLigne']) )
    {
    die('{"Reponse":0,"ligne":"variable(s) non déclarée(s)"}');
    }

    Par contre, ça voudrait dire que c'est le passage de paramètres qui ne fonctionnent pas :


    Quelque part par là  mais je ne sais pas trop :



    NSDictionary *parameters = @{@id:@1,@id_category:@1, @NumLigne:[NSString stringWithFormat:@%ld,_NumLigne]};
    NSError *errorJSON = nil;
    NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:&errorJSON];
    if (errorJSON){NSLog(@Ooops, invalid parameters);}

    NSURL *url=[NSURL URLWithString:@URL_DU_SCRIPT_LOGIN];

    NSString *postLength = [NSString stringWithFormat:@%lu, (unsigned long)[postData length]];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:url];
    [request setHTTPMethod:@POST];
    [request setValue:postLength forHTTPHeaderField:@Content-Length];
    [request setValue:@application/json forHTTPHeaderField:@Accept];
    [request setValue:@application/x-www-form-urlencoded forHTTPHeaderField:@Content-Type];
    [request setHTTPBody:postData];


    Sinon pour répondre à  votre question Larme, voici mon test sur cocoarestclient en pièce jointe. 


     


    Merci beaucoup pour votre aide. 


     


    Dans le même temps, je suis en train de regarder comment faire en swift. 


     


     


     


  • id_category vs id_categorie


  • Bonjour,


    Effectivement il y avait cette erreur sur id_categorie!

    Par contre ca ne fonctionne toujours pas, j'obtiens toujours la même chose : variable non déclarée.

    Comme si je ne passais pas de paramètres au script.
  • Il y a moyen dans ton php que tu regardes $_POST ?


  • Bonsoir,


     


    J'ai écrit les valeurs de $_POST dans un fichier et je vois qu'en passant par l'application les 3 valeurs sont vides :


     


    id = 


    id_categorie = 

    NumLigne = 
  • LarmeLarme Membre
    janvier 2017 modifié #19

    ça serait étrange que cela soit gérer de cette manière sur du POST, mais essayes en mettant 



    http://localhost/login.php?id=1&id_categorie=1&NumLigne=1 

  • Quand je testes cette URL directement dans un navigateur, j'obtiens la même erreur :


     


    {"Réponse":0,"ligne":"Variable(s) non déclarée(s)"}


  • Bonsoir,


     


    J'ai testé le script en changeant la récupération des variables de POST en GET et là  le script fonctionne correctement. 


     


    Je voudrais donc essayer de changer le code de l'appli pour passer l'appel en GET. 


    Pourriez vous m'aider svp ?


     


    Merci d'avance. 


     


    Bonne soirée.



  • Je voudrais donc essayer de changer le code de l'appli pour passer l'appel en GET.





    Je pense que l'utilisation de URLComponents et URLQueryItem est recommandé pour éviter les problèmes de construction de requêtes déjà .



    NSURLComponents & NSURLQueryItem devraient t'aider à  former le chemin de l'URL correctement, avec le "?", les "=", et les clés/valeurs qu'il faut.


  • Bonjour,


     


    Désolé pour ma réponse très tardive mais je n'ai pas pu tester avant. 


     


    J'ai enfin résolu mon souci, vous aviez raison, en utilisant NSURLComponents et NSURLQueryItem, ça fonctionne j'arrive bien à  récupérer ma réponse en son. 


     


    Voici le code que j'ai fait : 



    NSURLComponents *components = [NSURLComponents componentsWithString:@http://localhost/login.php];

    NSURLQueryItem *cat = [NSURLQueryItem queryItemWithName:@cat value:@1];
    NSURLQueryItem *ident = [NSURLQueryItem queryItemWithName:@id value:@1];
    NSURLQueryItem *NumLigne = [NSURLQueryItem queryItemWithName:@NumLigne value:[NSString stringWithFormat:@%lu, _NumLigne]];
    components.queryItems = @[; ident, cat, NumLigne ];
    NSLog(@%@", components.URL);

    NSURL *url = [components URL];

    Merci à  tous pour votre aide très précieuse. 


    Bonne soirée.


Connectez-vous ou Inscrivez-vous pour répondre.