156 votes

Comment faire un appel SOAP en PHP en utilisant la classe SoapClient

J'ai l'habitude d'écrire du code PHP, mais je n'utilise pas souvent le codage orienté objet. Je dois maintenant interagir avec SOAP (en tant que client) et je ne parviens pas à maîtriser la syntaxe. Je dispose d'un fichier WSDL qui me permet d'établir correctement une nouvelle connexion à l'aide de la classe SoapClient. Cependant, je ne parviens pas à effectuer l'appel correct et à obtenir des données en retour. J'ai besoin d'envoyer les données suivantes (simplifiées) :

  • Numéro de contact
  • Nom du contact
  • Description générale
  • Montant

Il y a deux fonctions définies dans le document WSDL, mais je n'ai besoin que d'une seule ("FirstFunction" ci-dessous). Voici le script que j'exécute pour obtenir des informations sur les fonctions et les types disponibles :

$client = new SoapClient("http://example.com/webservices?wsdl");
var_dump($client->__getFunctions()); 
var_dump($client->__getTypes()); 

Et voici la sortie qu'il génère :

array(
  [0] => "FirstFunction Function1(FirstFunction $parameters)",
  [1] => "SecondFunction Function2(SecondFunction $parameters)",
);

array(
  [0] => struct Contact {
    id id;
    name name;
  }
  [1] => string "string description"
  [2] => string "int amount"
}

Disons que je veux faire un appel à la FirstFunction avec les données :

  • ID de contact : 100
  • Nom de contact : John
  • Description générale : Baril de pétrole
  • Montant : 500

Quelle serait la bonne syntaxe ? J'ai essayé toutes sortes d'options, mais il semble que la structure des savons soit assez flexible et qu'il y ait de nombreuses façons de procéder. Je n'ai pas non plus réussi à trouver la solution dans le manuel...


UPDATE 1 : essayé l'échantillon de MMK :

$client = new SoapClient("http://example.com/webservices?wsdl");

$params = array(
  "id" => 100,
  "name" => "John",
  "description" => "Barrel of Oil",
  "amount" => 500,
);
$response = $client->__soapCall("Function1", array($params));

Mais je reçois cette réponse : Object has no 'Contact' property . Comme vous pouvez le voir dans la sortie de getTypes() il existe un struct appelé Contact J'imagine donc que je dois faire en sorte que mes paramètres incluent les données de contact, mais la question est : comment ?

MISE À JOUR 2 : J'ai également essayé ces structures, même erreur.

$params = array(
  array(
    "id" => 100,
    "name" => "John",
  ),
  "Barrel of Oil",
  500,
);

Ainsi que :

$params = array(
  "Contact" => array(
    "id" => 100,
    "name" => "John",
  ),
  "description" => "Barrel of Oil",
  "amount" => 500,
);

Erreur dans les deux cas : Object has no 'Contact' property

190voto

Oscar Jara Points 5104

Voici ce que vous devez faire.

J'ai essayé de recréer la situation...


  • Pour cet exemple, j'ai créé un exemple de WebService (WS) .NET avec un nom d'utilisateur et un mot de passe. WebMethod appelé Function1 qui attend les paramètres suivants :

Fonction1(Contact Contact, string description, int montant)

  • Contact est juste un modèle qui a des getters et setters pour id y name comme dans votre cas.

  • Vous pouvez télécharger l'échantillon .NET WS à l'adresse suivante :

https://www.dropbox.com/s/6pz1w94a52o5xah/11593623.zip


Le code.

C'est ce que vous devez faire du côté de PHP :

(Testé et fonctionnant)

<?php
// Create Contact class
class Contact {
    public function __construct($id, $name) 
    {
        $this->id = $id;
        $this->name = $name;
    }
}

// Initialize WS with the WSDL
$client = new SoapClient("http://localhost:10139/Service1.asmx?wsdl");

// Create Contact obj
$contact = new Contact(100, "John");

// Set request params
$params = array(
  "Contact" => $contact,
  "description" => "Barrel of Oil",
  "amount" => 500,
);

// Invoke WS method (Function1) with the request params 
$response = $client->__soapCall("Function1", array($params));

// Print WS response
var_dump($response);

?>

Je teste tout ça.

  • Si vous le faites print_r($params) vous verrez la sortie suivante, comme votre WS s'y attendrait :

Array ( [Contact] => Contact Object ( [id] => 100 [name] => John ) [description] => Baril de pétrole [montant] => 500 )

  • Lorsque j'ai débogué l'échantillon .NET WS, j'ai obtenu le résultat suivant :

enter image description here

(Comme vous pouvez le voir, Contact n'est pas null ni les autres paramètres. Cela signifie que votre requête a été effectuée avec succès du côté de PHP.)

  • La réponse de l'échantillon .NET WS était celle attendue et voici ce que j'ai obtenu du côté PHP :

object(stdClass)[3] public 'Function1Result' => string 'Detailed détaillées de votre demande ! id : 100, name : John, description : Baril de pétrole, montant : 500' (length=98)


Bon codage !

3 votes

Parfait ! J'ai agi comme si je connaissais un peu plus les services SOAP que je ne le faisais réellement et cela m'a permis d'arriver là où je devais être.

1 votes

Je n'ai pas posé la question, sinon je l'aurais fait. La question et la réponse ont reçu un vote positif de ma part.

4 votes

@user devrait l'accepter :) BTW, très belle réponse, complète et très claire. +1

83voto

Salvador P. Points 357

Vous pouvez également utiliser les services SOAP de cette manière :

<?php 
//Create the client object
$soapclient = new SoapClient('http://www.webservicex.net/globalweather.asmx?WSDL');

//Use the functions of the client, the params of the function are in 
//the associative array
$params = array('CountryName' => 'Spain', 'CityName' => 'Alicante');
$response = $soapclient->getWeather($params);

var_dump($response);

// Get the Cities By Country
$param = array('CountryName' => 'Spain');
$response = $soapclient->getCitiesByCountry($param);

var_dump($response);

Il s'agit d'un exemple avec un service réel, et il fonctionne lorsque l'url est en place.

Juste au cas où le http://www.webservicex.net est en panne.

Voici un autre exemple en utilisant le service web d'exemple de Services Web XML du W3C vous pouvez trouver plus d'informations sur le lien.

<?php
//Create the client object
$soapclient = new SoapClient('https://www.w3schools.com/xml/tempconvert.asmx?WSDL');

//Use the functions of the client, the params of the function are in
//the associative array
$params = array('Celsius' => '25');
$response = $soapclient->CelsiusToFahrenheit($params);

var_dump($response);

// Get the Celsius degrees from the Farenheit
$param = array('Fahrenheit' => '25');
$response = $soapclient->FahrenheitToCelsius($param);

var_dump($response);

Cela fonctionne et renvoie les valeurs de température converties.

J'espère que cela vous aidera.

0 votes

J'obtiens l'erreur suivante : object(stdClass)#70 (1) { ["GetWeatherResult"]=> string(14) "Data Not Found" } Une idée ?

0 votes

Il semble qu'ils aient changé les ficelles des villes. Je viens de mettre à jour l'exemple avec un autre appel à un autre service qu'ils fournissent et ça marche. J'ai essayé d'utiliser les chaînes qu'ils renvoient comme villes, mais cela ne semble pas fonctionner correctement, de toute façon la fonction getCitiesByCountry() sert d'exemple sur la façon de faire un appel.

0 votes

Cet exemple est à nouveau en panne

32voto

MMK Points 706

Initialiser d'abord les webservices :

$client = new SoapClient("http://example.com/webservices?wsdl");

Ensuite, définissez et passez les paramètres :

$params = array (
    "arg0" => $contactid,
    "arg1" => $desc,
    "arg2" => $contactname
);

$response = $client->__soapCall('methodname', array($params));

Notez que le nom de la méthode est disponible dans le WSDL comme nom d'opération, par exemple :

<operation name="methodname">

1 votes

Merci ! J'ai essayé mais j'obtiens l'erreur "Object has no 'Contact' property". Je vais mettre à jour ma question avec tous les détails. Avez-vous des idées ?

0 votes

@user16441 Pouvez-vous afficher le WSDL et le schéma du service ? Je commence généralement par déterminer le XML attendu par le service, puis j'utilise WireShark pour déterminer ce que mon client envoie réellement.

24voto

Tín Phạm Points 89

Je ne sais pas pourquoi mon service web a la même structure que vous mais il n'a pas besoin de classe pour les paramètres, c'est juste un tableau.

Par exemple : - Mon WSDL :

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:ns="http://www.kiala.com/schemas/psws/1.0">
    <soapenv:Header/>
    <soapenv:Body>
        <ns:createOrder reference="260778">
            <identification>
                <sender>5390a7006cee11e0ae3e0800200c9a66</sender>
                <hash>831f8c1ad25e1dc89cf2d8f23d2af...fa85155f5c67627</hash>
                <originator>VITS-STAELENS</originator>
            </identification>
            <delivery>
                <from country="ES" node=””/>
                <to country="ES" node="0299"/>
            </delivery>
            <parcel>
                <description>Zoethout thee</description>
                <weight>0.100</weight>
                <orderNumber>10K24</orderNumber>
                <orderDate>2012-12-31</orderDate>
            </parcel>
            <receiver>
                <firstName>Gladys</firstName>
                <surname>Roldan de Moras</surname>
                <address>
                    <line1>Calle General Oraá 26</line1>
                    <line2>(4º izda)</line2>
                    <postalCode>28006</postalCode>
                    <city>Madrid</city>
                    <country>ES</country>
                </address>
                <email>gverbruggen@kiala.com</email>
                <language>es</language>
            </receiver>
        </ns:createOrder>
    </soapenv:Body>
</soapenv:Envelope>

I var_dump :

var_dump($client->getFunctions());
var_dump($client->getTypes());

Voici le résultat :

array
  0 => string 'OrderConfirmation createOrder(OrderRequest $createOrder)' (length=56)

array
  0 => string 'struct OrderRequest {
 Identification identification;
 Delivery delivery;
 Parcel parcel;
 Receiver receiver;
 string reference;
}' (length=130)
  1 => string 'struct Identification {
 string sender;
 string hash;
 string originator;
}' (length=75)
  2 => string 'struct Delivery {
 Node from;
 Node to;
}' (length=41)
  3 => string 'struct Node {
 string country;
 string node;
}' (length=46)
  4 => string 'struct Parcel {
 string description;
 decimal weight;
 string orderNumber;
 date orderDate;
}' (length=93)
  5 => string 'struct Receiver {
 string firstName;
 string surname;
 Address address;
 string email;
 string language;
}' (length=106)
  6 => string 'struct Address {
 string line1;
 string line2;
 string postalCode;
 string city;
 string country;
}' (length=99)
  7 => string 'struct OrderConfirmation {
 string trackingNumber;
 string reference;
}' (length=71)
  8 => string 'struct OrderServiceException {
 string code;
 OrderServiceException faultInfo;
 string message;
}' (length=97)

Donc dans mon code :

    $client  = new SoapClient('http://packandship-ws.kiala.com/psws/order?wsdl');

    $params = array(
        'reference' => $orderId,
        'identification' => array(
            'sender' => param('kiala', 'sender_id'),
            'hash' => hash('sha512', $orderId . param('kiala', 'sender_id') . param('kiala', 'password')),
            'originator' => null,
        ),
        'delivery' => array(
            'from' => array(
                'country' => 'es',
                'node' => '',
            ),
            'to' => array(
                'country' => 'es',
                'node' => '0299'
            ),
        ),
        'parcel' => array(
            'description' => 'Description',
            'weight' => 0.200,
            'orderNumber' => $orderId,
            'orderDate' => date('Y-m-d')
        ),
        'receiver' => array(
            'firstName' => 'Customer First Name',
            'surname' => 'Customer Sur Name',
            'address' => array(
                'line1' => 'Line 1 Adress',
                'line2' => 'Line 2 Adress',
                'postalCode' => 28006,
                'city' => 'Madrid',
                'country' => 'es',
                ),
            'email' => 'test.ceres@yahoo.com',
            'language' => 'es'
        )
    );
    $result = $client->createOrder($params);
    var_dump($result);

mais avec succès !

3 votes

Votre exemple est plus utile, car il montre les dépendances structurelles.

5voto

Umesh Chavan Points 432

Si vous créez l'objet de SoapParam, cela résoudra votre problème. Créer une classe et la mapper avec le type d'objet donné par WebService, initialiser les valeurs et envoyer la requête. Voir l'exemple ci-dessous.

struct Contact {

    function Contact ($pid, $pname)
    {
      id = $pid;
      name = $pname;
  }
}

$struct = new Contact(100,"John");

$soapstruct = new SoapVar($struct, SOAP_ENC_OBJECT, "Contact","http://soapinterop.org/xsd");

$ContactParam = new SoapParam($soapstruct, "Contact")

$response = $client->Function1($ContactParam);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X