soap et problème de persistence mysql

soap et problème de persistence mysql - PHP - Programmation

Marsh Posté le 28-03-2008 à 17:30:24    

Bonjour,
 
Je suis en train de mettre en place un webservice et je veux faire un système d'identification.
Voici le code de la page client.

Code :
  1. $client = new SoapClient(null,array('location'=>'http://xxxx.com/adserverPersist.php','uri'=>'http://xxxx.com/'));
  2. $login = 'login';
  3. $pass = 'pass';
  4. $client->connection($login,$pass);
  5. $rep2 = $client->doSomething();


et voici la class appelée par le SoapServer :

Code :
  1. class Foo {
  2. private $db;
  3. private $login;
  4. private $pass;
  5. public function __construct(){}
  6. public connection($login,$pass){
  7.  $this->login = $login;
  8.  $this->pass = $pass;
  9.  $this->connectDb();
  10. }
  11. private function connectDb(){
  12.  $this->db = new MySQL('localhost',$this->login,$this->pass,'database');
  13. }
  14. public function doSomething(){
  15.  if (!$this->db->isConnected()){
  16.   $this->connectDb();
  17.  }
  18.  $sql = 'select * from table';
  19.  $rqt = $this->db->query($sql);
  20. }
  21. public function doSomethingElse(){
  22.  if (!$this->db->isConnected()){
  23.   $this->connectDb();
  24.  }
  25.  $sql = 'select * from table2';
  26.  $rqt = $this->db->query($sql);
  27. }
  28. }


Si j'essaye d'appeler la méthode doSomething(), la connection est perdue et je dois forcer la reconnection
à la base de donnée pour pouvoir faire mes requetes.
 
Quelqu'un pourrait me dire s'il y a une possibilité de mettre une sorte de persistence en place pour garder
la connection à la base de donnée active ? Mais peut-être est-ce impossible et il faudra au début de chaque
appel de méthode via le webservice que je me reconnecte à la BDD ?  
 
Même si vous n'avez pas la réponse complète, une piste m'aiderai déjà pas mal.
 
Merci d'avance pour votre aide.  
 
Thomas.

Reply

Marsh Posté le 28-03-2008 à 17:30:24   

Reply

Marsh Posté le 31-03-2008 à 15:44:10    

Salut,
 
J'ai moi aussi le même problème :
 
Le code du client :
 

Code :
  1. <?php
  2. ini_set("soap.wsdl_cache_enabled", "0" );
  3. $client = new SoapClient("http://127.0.0.1/test/captain.wsdl",
  4.    array('soap_version' => SOAP_1_1, 'encoding' => 'ISO-8859-1', 'style' => SOAP_RPC, 'use' => SOAP_ENCODED));
  5. try
  6. {
  7.   $client->createCaptain("Titi", 20);
  8.   //Le code qui pose problème...
  9.   echo "Nom : ".$client->getCaptainName();
  10. }
  11. catch (SoapFault $exception)
  12. {
  13.   echo "Exception: ".$exception;
  14. }
  15. ?>


 
Le serveur avec les classes Captain et Person :
 

Code :
  1. <?php
  2. class Person
  3. {
  4.   private $name = "Default Name";
  5.   private $age = 99;
  6.   /**
  7.    * Constructeur de la classe
  8.    *
  9.    * @param string $name
  10.    * @param string $firstname
  11.    * @param integer $age
  12.    */
  13.   public function __construct($name, $age)
  14.   {
  15.     $this->name = $name;
  16.     $this->age = (int)$age;
  17.   }
  18.   /**
  19.    * Retourne le nom
  20.    *
  21.    * @return string
  22.    */
  23.   public function getName()
  24.   {
  25.     return $this->name;
  26.   }
  27. }
  28. class Captain
  29. {
  30.   private $captn = null;
  31.   /**
  32.    * Crée un nouveau Capitaine
  33.    *
  34.    * @param string $name
  35.    * @param integer $age
  36.    */
  37.   public function createCaptain($name, $age)
  38.   {
  39.     $this->captn = new Person($name, $age);
  40.   }
  41.   /**
  42.    * Retourne le nom du Capitaine
  43.    *
  44.    * @return string
  45.    */
  46.   public function getCaptainName()
  47.   {
  48.     return $this->captn->getName();
  49.   }
  50. }
  51. // disabling WSDL cache
  52. ini_set("soap.wsdl_cache_enabled", "0" );
  53. // create the new object SoapServer
  54. $server = new SoapServer("http://127.0.0.1/test/captain.wsdl",
  55.    array('soap_version' => SOAP_1_1, 'encoding' => 'ISO-8859-1', 'style' => SOAP_RPC, 'use' => SOAP_ENCODED));
  56. // add class
  57. $server->setClass("Captain" );
  58. // ready to receice xml
  59. $server->handle();
  60. ?>


 
Du coup, après avoir instancié la classe Person via la méthode createCaptain, l'objet ainsi créé est inopérant. C'est bizarre...
 
Faudrait-il stocker l'objet créé en Session :??:  
 
Si qq'un a une idée, ça m'intéresse !!
Lionel.
 

Reply

Marsh Posté le 31-03-2008 à 17:33:28    

pot2yaourt a écrit :


Du coup, après avoir instancié la classe Person via la méthode createCaptain, l'objet ainsi créé est inopérant. C'est bizarre...


Non, c'est normal.
Une variable php meurt à la fin du script.

 

Pour avoir ce que tu essaies d'avoir il faut que ta méthode createCaptain retourne le captain créé, et que tu manipules cet objet, plus le soapclient.
Et le problème est identique au-dessus, en effet.


Message édité par skeye le 31-03-2008 à 17:37:35

---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 31-03-2008 à 20:41:06    

Salut !
 
Merci pour ta réponse... effectivement, après qqs modifications ça fonctionne, mais la syntaxe est plutôt bizarre, je ne m'attendais pas à ça.
 
La liste des modifs :
 
Dans la classe Captain, j'ai modifié, entre autres, la méthode createCaptain afin qu'elle retourne l'objet Person qui a été créé :
 

Code :
  1. // Disparition de l'attribut $captn et de la méthode getCaptainName() qui ne sert plus à rien !
  2. class Captain
  3. {
  4.   public function createCaptain($name, $age)
  5.   {
  6.       return new Person($name, $age);
  7.   }
  8. }


 
Quant au client, voici comment je l'ai modifié :
 

Code :
  1. try
  2. {
  3.   $object = $client->createCaptain("Titi", 20);
  4.   // Le code modifié !   
  5.   echo "Nom : ".$object->name;
  6. }
  7. catch (SoapFault $exception)
  8. {
  9.   echo "Exception: ".$exception;
  10. }


 
Mais voilà, d'où sort ce ->name ??  En fait, il s'agit de l'attribut de la classe Person !
 

Code :
  1. class Person
  2. {
  3.   // C'est cet attribut qui est utilisé !
  4.   private $name = "Default Name";
  5.   public function __construct($name, $age)
  6.   {
  7.     $this->name = $name;
  8.     $this->age = (int)$age;
  9.   }
  10.   [...]
  11. }


 
Donc, si la classe Person est modifiée ainsi :
 

Code :
  1. class Person
  2. {
  3.   // Nouveau nom de l'attribut
  4.   private $nameXYZ = "Default Name";
  5.   public function __construct($name, $age)
  6.   {
  7.     $this->nameXYZ = $name;
  8.     $this->age = (int)$age;
  9.   }
  10.   [...]
  11. }


 
Le code du client ressemblera alors à ceci :
 

Code :
  1. try
  2. {
  3.   $object = $client->createCaptain("Titi", 20);
  4.   // Plutôt bizarre, non ???
  5.   echo "Nom : ".$object->nameXYZ;
  6. }
  7. catch (SoapFault $exception)
  8. {
  9.   echo "Exception: ".$exception;
  10. }


 
Enfin voilà, c'est peut-être tout à fait normal, à moins que ce soit moi qui m'y suis mal pris ?!, mais je trouvais la façon de coder un peu bizarre.
Si qq'un à un avis sur la question, ça m'intéresse !
 
Lionel.

Reply

Marsh Posté le 31-03-2008 à 20:44:39    

pourquoi ton objet Person() n'aurait pas une méthode name() qui retourne le nom?


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 31-03-2008 à 21:06:23    

Justement, la classe Person dispose bien d'une méthode getName() qui retourne le nom mais ça ne fonctionne pas !
 
J'obtiens le message d'erreur suivant : Fatal error: Call to undefined method stdClass::getName()  
 
Le code du client modifié :

Code :
  1. try
  2. {
  3.   $object = $client->createCaptain("Titi", 20);
  4.   // Appel de la méthode getName() de la classe Person
  5.   echo "Nom : ".$object->getName();
  6. }
  7. catch (SoapFault $exception)
  8. {
  9.   echo "Exception: ".$exception;
  10. }

Reply

Marsh Posté le 31-03-2008 à 21:10:31    

Ok, j'ai jamais joué avec la lib soap de php, mais c'est possible, et même probable après réflexion que ça ne retourne pas les objets avec leurs méthodes...fais un print_r($object) pour voir ce que tu récupères?


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 31-03-2008 à 21:29:03    

Voilà le résultat du print_r($object); :
 
stdClass Object ( [name] => Titi [age] => 20 )
 
ou encore ceci avec un echo var_export($object, true); :
 
stdClass::__set_state(array( 'name' => 'Titi', 'age' => 20, ))
 
C'est en voyant ce résultat que j'ai testé : $object->name et par miracle ça a marché ! Coup de bol !
 
Au final je trouve ça quand même un peu bizarre... en faisant $object->name c'est comme si on avait accès à un attribut privé. Faudra que je fasse quelques essais pour voir comment ça réagit avec un client dotNet, en C# par exemple.

Reply

Marsh Posté le 31-03-2008 à 21:30:05    

pot2yaourt a écrit :

Voilà le résultat du print_r($object); :
 
stdClass Object ( [name] => Titi [age] => 20 )
 
ou encore ceci avec un echo var_export($object, true); :
 
stdClass::__set_state(array( 'name' => 'Titi', 'age' => 20, ))
 
C'est en voyant ce résultat que j'ai testé : $object->name et par miracle ça a marché ! Coup de bol !
 
Au final je trouve ça quand même un peu bizarre... en faisant $object->name c'est comme si on avait accès à un attribut privé. Faudra que je fasse quelques essais pour voir comment ça réagit avec un client dotNet, en C# par exemple.


 
tu n'as pas accès à un attribut privé du tout. Tu as accès au contenu du flux xml que t'as retourné ton webservice...


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 31-03-2008 à 21:52:41    

skeye a écrit :


tu n'as pas accès à un attribut privé du tout. Tu as accès au contenu du flux xml que t'as retourné ton webservice...


 
Oui, c'est exact, ce que je voulais dire c'est que le print_r tout comme le var_export font apparaître le nom d'un attribut privé de la classe. L'attribut étant privé, on n'a pas à savoir comment il s'appelle.

Reply

Marsh Posté le 31-03-2008 à 21:52:41   

Reply

Marsh Posté le 31-03-2008 à 21:54:37    

pot2yaourt a écrit :


 
Oui, c'est exact, ce que je voulais dire c'est que le print_r tout comme le var_export font apparaître le nom d'un attribut privé de la classe. L'attribut étant privé, on n'a pas à savoir comment il s'appelle.


 
non, c'est là que tu te trompes. TU ne récupères pas un Person, mais un objet standard.


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 31-03-2008 à 22:21:38    

Ah ok, j'avais effectivement pas vu ça comme ça... en fait je souhaitais à tout prix récupérer un objet Person, c'est pour ça !
 
Encore merci pour toutes ces infos !
Lionel.

Reply

Marsh Posté le 31-03-2008 à 22:23:33    

pot2yaourt a écrit :

Ah ok, j'avais effectivement pas vu ça comme ça... en fait je souhaitais à tout prix récupérer un objet Person, c'est pour ça !

 

Encore merci pour toutes ces infos !
Lionel.

 

il y a peut-être moyen, mais en incluant ta classe Person dans le client, et faut voir si ça passe...sinon je pense pas qu'il veuille.


Message édité par skeye le 31-03-2008 à 22:23:40

---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 01-04-2008 à 11:36:11    

Merci pour toutes vos réponses même si elles ne répondent pas au problème.
 
Retourner l'objet et faire un print_r(), ne me servira à rien dans mon cas car, je vais bien récupérer les valeurs des variables standards (int, string, etc...). Mais pour une connection à une base de donnée, je suis automatiquement déconnecté.
 

Citation :

il y a peut-être moyen, mais en incluant ta classe Person dans le client, et faut voir si ça passe...sinon je pense pas qu'il veuille.


 
De plus, il ne faut surtout pas faire çà, car le client du webservice n'est pas censé connaître le moteur et donc les objets utilisés sur la partie serveur. Si le client connait la class Person, à quoi sert de faire un webservice ?
 

Reply

Marsh Posté le 01-04-2008 à 11:39:59    

madeintom a écrit :

Merci pour toutes vos réponses même si elles ne répondent pas au problème.

 

Retourner l'objet et faire un print_r(), ne me servira à rien dans mon cas car, je vais bien récupérer les valeurs des variables standards (int, string, etc...). Mais pour une connection à une base de donnée, je suis automatiquement déconnecté.

 

Non, tu n'es pas déconnecté. Tu fais exactement la même erreur que lui, en pensant que deux appels à des fonctions différentes d'un même webservice par le même programme ne sont pas traités individuellement mais en groupe par le serveur.

 

[edit]

 

Je ne vois même pas pour quelle raison farfelue ton client saurait que le serveur doit se connecter à une base de données, d'ailleurs.


Message édité par skeye le 01-04-2008 à 11:42:31

---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 01-04-2008 à 11:48:54    

Donc tu veux dire que chaque méthode de l'objet utilisé par le webservice doit se reconnecter à chaque appel du client ? En soit, je peux comprendre.  
 
Mais, donc on en revient à ma question du départ... N'existe-t-il pas une solution pour faire "persister" la connection active à la base de donnée pendant un certain temps ?
 
Suis-je obligé d'avoir le code suivant :
 

Code :
  1. class Foo {
  2. private $db;
  3. private $login;
  4. private $pass;
  5. public function __construct(){}
  6. public connection($login,$pass){
  7. $this->login = $login;
  8. $this->pass = $pass;
  9. }
  10. private function connectDb(){
  11. $this->db = new MySQL('localhost',$this->login,$this->pass,'database');
  12. }
  13. public function doSomething(){
  14.   $this->connectDb();
  15. $sql = 'select * from table';
  16. $rqt = $this->db->query($sql);
  17. }
  18. public function doSomethingElse(){
  19.   $this->connectDb();
  20. $sql = 'select * from table2';
  21. $rqt = $this->db->query($sql);
  22. }
  23. }

Reply

Marsh Posté le 01-04-2008 à 11:55:36    

Oui, tu es grosso modo obligé. Il faut que tu gardes en mémoire chaque fonction publiée par ton webservice sera exécutée par le serveur comme un script autonome...et une ressource de connexion ne peut pas persister entre deux scripts.


---------------
Can't buy what I want because it's free -
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed