Php sabun istemcisi örnekleri. PHP'de SOAP istemci-sunucu uygulaması yazma

Bir web servisine bağlanmam gerekiyor ve sahip olduğum tek şey bu:

    Örnek çağrı:

    Kullanıcı adı Şifre

    Bu işlevin bir dize döndürdüğünü biliyorum;

Şu ana kadar yaptığım şey bu:

    Yalnızca 1. adımda belirtilen WSDL adresini ekleyerek bir Hizmet Referansı oluşturuldu.

    Bir web hizmeti örneği oluşturuldu ve işlevi gerekli tüm parametrelerle çağırdı, ancak başlığın kullanıcı ve parolasını değil.

Nasıl devam etmeliyim? Şimdiden teşekkür ederim.

1 cevap

Kimlik bilgilerinizi eklemeniz gerekiyorsa burası başlamak için iyi bir yer olabilir; Onları bir şekilde aldığına göre, bunu yapmak zorunda olabileceğini düşünüyorum. Kimlik bilgilerinizi ekleyeceğiniz kısım aşağıdadır:

Kullanıcı AdıToken userToken = new Kullanıcı AdıToken(kullanıcıAdı, şifre, PasswordOption.SendHashed); Hizmet1 hizmetProxy = yeni Hizmet1(); SoapContext requestContext = serviceProxy.RequestSoapContext; requestContext.Security.Tokens.Add(userToken);

  1. Kimlik bilgilerinizi, türü Microsoft.Web.Services2.Security.Tokens ad alanına ait olan belirli bir belirtece yerleştirerek ekleyin.
  2. Hizmetiniz için bir proxy oluşturun (yukarıdaki örnekte serviceProxy'de)
  3. İstek başlığınıza requestSoapContext hizmetiniz aracılığıyla erişin
  4. İsteğe belirteç ekleyin

Ayrıca, web hizmeti spesifikasyonuyla ilgili olduğundan adresteki "?Wsdl" kısmını atlayabileceğinizi düşünüyorum. Bu tamamlandıktan sonra, işlevi çağırmayı deneyebilir ve her şeyin nasıl çalıştığını görebilirsiniz: eğer işlevin bir şey döndürmesi gerekiyorsa, ne beklediğinizi kontrol edin.

PHP kodu yazmaya alışkınım ama nesne yönelimli kodlamayı pek kullanmıyorum. Şimdi SOAP ile (istemci olarak) etkileşim kurmam gerekiyor ve sözdizimini doğru anlayamıyorum. SoapClient sınıfını kullanarak yeni bir bağlantıyı düzgün şekilde yapılandırmamı sağlayan bir WSDL dosyam var. Ancak doğru aramayı yapıp verileri geri alamıyorum. Aşağıdaki (basitleştirilmiş) verileri göndermem gerekiyor:

  • İletişim Kimliği
  • Kişi adı
  • Genel açıklama
  • Toplam

WSDL belgesinde iki işlev var, ancak yalnızca birine ihtiyacım var (aşağıdaki "FirstFunction"). Kullanılabilir işlevler ve türler hakkında bilgi almak için çalıştırdığım komut dosyası:

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

Ve işte ürettiği sonuç:

Array( => "BirinciFonksiyon Fonksiyonu1(BirinciFonksiyon $parametreler)", => "İkinciFonksiyon Fonksiyon2(İkinciFonksiyon $parametreler)",); array( => struct Contact ( id id; name name; ) => string "string açıklama" => string "int miktar" )

Diyelim ki FirstFunction'ı verilerle çağırmak istiyorum:

  • İletişim Kimliği: 100
  • İrtibat kurulacak kişi: John
  • Genel Açıklama: Petrol Varil
  • Tutar: 500

Doğru sözdizimi ne olurdu? Her türlü varyasyonu denedim ama sabunun yapısı oldukça esnek gibi görünüyor, dolayısıyla bunu yapmanın çok fazla yolu var. Bunu kılavuzdan anlayamadım...

GÜNCELLEME 1: MMK'dan örnek örnek:

$client = new SoapClient("http://example.com/webservices?wsdl"); $params = array("id" => 100, "name" => "John", "description" => "Petrol Varil", "miktar" => 500,); $yanıt = $client->__soapCall("Function1", array($params));

Ancak şu yanıtı alıyorum: Nesnenin "Contact" özelliği yok. getTypes() çıktısında görebileceğiniz gibi, Contact adında bir yapı var, bu yüzden sanırım bir şekilde parametrelerimin Contact verilerini içerdiğini açıklamam gerekiyor, ancak soru şu: nasıl?

GÜNCELLEME 2: Bu yapıları da denedim, aynı hata.

$params = array(array("id" => 100, "name" => "John",), "Petrol Varil", 500,);

Birlikte:

$params = array("İletişim" => array("id" => 100, "name" => "John",), "description" => "Petrol Varil", "miktar" => 500,);

Her iki durumda da hata: nesnenin "İletişim" özelliği yok

8 cevap

Yapman gereken bu.

Sadece bilmek için, senin durumunu yeniden yaratmaya çalıştım...

  • Bu örnekte, Function1 adında bir WebMethod kullanarak bir .NET web hizmeti oluşturdum ve parametreler şunlardır:

Fonksiyon1(pin pini, dize açıklaması, int sayısı)

    Kişinin yalnızca sizin durumunuzda olduğu gibi kimlik ve ad için alıcıları ve ayarlayıcıları olan bir fasulye sınıfı vardır.

    Bu .NET web hizmetini şununla yükleyebilirsiniz:

Kod.

Bu tarafta yapmanız gereken şey bu PHP:

(Test edildi ve çalışıyor)

kimlik = $kimlik; $this->isim = $isim; )) ) /* Web hizmetini WSDL'nizle başlatın */ $client = new SoapClient("http://localhost:10139/Service1.asmx?wsdl"); /* İletişim Nesnenizi doldurun */ $contact = new Contact(100, "John"); /* İstek için parametrelerinizi ayarlayın */ $params = array("Contact" => $contact, "description" => "Petrol Varil", "miktar" => 500,); /* Bu durumda parametrelerinizle birlikte web hizmeti yöntemini çağırın: Function1 */ $response = $client->__soapCall("Function1", array($params)); /* Web hizmeti yanıtını yazdır */ var_dump($response); ?>

Çalıştığını nasıl bileceğim?

  • Eğer print_r($params); Bu çıktıyı göreceksiniz çünkü web servisiniz şunu bekliyor:

Dizi ([İletişim] => Temas nesnesi ( => 100 => John) [açıklama] => Yağ varili [miktar] => 500)

  • .NET web hizmeti örneğinde hata ayıkladığımda aşağıdakileri elde ettim:

(Gördüğünüz gibi Contact nesnesi ve diğer parametreler null değil, bu da isteğinizin PHP tarafından başarıyla tamamlandığı anlamına geliyor).

  • .NET web hizmetinden gelen yanıt beklendiği gibiydi ve PHP tarafında gösterildi:

object (stdClass) public "Function1Result" => string "İsteğinizin ayrıntıları! id: 100, isim: John, açıklama: Petrol varili, miktar: 500" (uzunluk = 98)

Bu yardımcı olur umarım :-)

SOAP hizmetlerini de kullanabilirsiniz:

"İspanya", "ŞehirAdı" => "Alicante"); $yanıt = $soapclient->getWeather($params); var_dump($yanıt); // Şehirleri Ülkeye Göre Al $param = array("ÜlkeAdı" => "İspanya"); $response = $soapclient->getCitiesByCountry($param); var_dump($yanıt);

Bu gerçek bir hizmete sahip bir örnektir ve işe yarar.

Bu yardımcı olur umarım.

İlk önce web servislerini başlatın:

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

Ardından parametreleri ayarlayın ve iletin:

$params = array("arg0" => $kişikimliği, "arg1" => $desc, "arg2" => $kişi adı); $yanıt = $client->__soapCall("methodname", array($params));

Yöntem adının WSDL'de işlem adı olarak mevcut olduğunu unutmayın; örneğin:

Web hizmetimin neden sizinkiyle aynı yapıya sahip olduğunu bilmiyorum, ancak parametre için bir sınıfa değil, yalnızca bir diziye ihtiyacı var.

Örneğin: - WSDL'im:

5390a7006cee11e0ae3e0800200c9a66 831f8c1ad25e1dc89cf2d8f23d2af...fa85155f5c67627 VITS-STALENS Zoet seni 0.100 10K24 2012-12-31 Gladys Roldan de Moras

Calle General Oraá 26 (4° izda) 28006 Madrid ES
[e-posta korumalı] es

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

İşte sonuç:

Array 0 => string "OrderConfirmation createOrder(OrderRequest $createOrder)" (uzunluk=56) array 0 => string "struct OrderRequest ( Kimlik tanımlama; Teslimat teslimatı; Koli paketi; Alıcı alıcı; string referansı; )" (uzunluk=130) 1 => string "struct Tanımlama ( string gönderen; string karması; string oluşturucu; )" (uzunluk=75) 2 => string "struct Teslimat ( Düğümden itibaren; Düğümden nereye; )" (uzunluk=41) 3 => string " struct Node ( string country; string node; )" (length=46) 4 => string "struct Parsel ( string açıklaması; ondalık ağırlık; string orderNumber; date orderDate; )" (length=93) 5 => string "struct Alıcı ( string name; string soyisim; Adres adresi; string e-posta; string dil; )" (uzunluk=106) 6 => string "struct Adres ( string satır1; string satır2; string postaKodu; string şehir; string ülke; )" (length=106) =99) 7 => string "struct OrderConfirmation ( string traceNumber; string reference; )" (length=71) 8 => string "struct OrderServiceException ( string code; OrderServiceException arıza bilgisi; dize mesajı; )" (uzunluk=97)

Yani kodumda:

$client = new SoapClient("http://packandship-ws.kiala.com/psws/order?wsdl"); $params = array("referans" => $orderId, "identification" => array("sender" => param("kiala", "sender_id"), "hash" => hash("sha512", $orderId . param("kiala", "gönderen_id") .param("kiala", "şifre")), "oluşturan" => null,), "teslimat" => array("from" => array("ülke" = > "es", "düğüm" => "",), "to" => dizi("ülke" => "es", "düğüm" => "0299")), "parsel" => dizi( "description" => "Açıklama", "ağırlık" => 0,200, "orderNumber" => $orderId, "orderDate" => tarih("Y-m-d")), "receiver" => array("firstName" => " Müşteri Adı", "soyadı" => "Müşteri Soyadı", "adres" => array("satır1" => "Satır 1 Adresi", "satır2" => "Satır 2 Adresi", "postalCode" => 28006, "şehir" => "Madrid", "ülke" => "es",), "e-posta" => " [e-posta korumalı]", "language" => "es")); $result = $client->createOrder($params); var_dump($result);

ama başardı!

Bu, SOAP işlevi "__call" için iyi bir örnektir. Ancak modası geçmiş.

Envio Internacional: "; $vem = $cliente->__call("CustoEMSInternacional",array($int_zona, $int_peso)); print $vem; print "

"; ?>

SOAP (Basit Nesne Erişim Protokolü), HTTP gibi mevcut web protokolleri üzerinden dağıtılmış uygulamalar arasında yapılandırılmış bilgi alışverişi yapmak için tasarlanmış XML tabanlı bir protokoldür. SOAP spesifikasyonu, XML mesajları tarafından kullanılan formatı, bunların nasıl işlenmesi gerektiğini, standart için bir dizi kodlama kuralını, veri türlerini ve uzaktan prosedür çağrıları ve çağrılara yanıtlar için kuralları tanımlar.

Web hizmetleri modaya uygun ve modern bir teknolojidir. Web hizmetleriyle ilgili teknolojilerin listesi neredeyse her gün artıyor ancak SOAP muhtemelen bunların en önemlisi. Web hizmetlerine erişim için hızla standart protokol haline geliyor. Uç noktalar arasında bilgi alışverişi yapmak için XML mesajlarını kullanır, ancak yine de ikili protokollerin bazı faydalarını sağlar. RPC (Uzaktan Prosedür Çağrıları) desteği başlangıçta SOAP protokolünün küçük özelliklerinden biriydi ancak artık en sık kullanılan özelliklerden biri haline geldi.

PHP 5 için SOAP uzantısı, PHP'de C dilinde SOAP desteğini organize etmeye yönelik ilk girişimdir. PHP'de yazılmış mevcut SOAP uygulamalarına göre birçok avantajı vardır; bunlardan en önemlisi hızdır. Şu anda uzantının deneysel olduğu düşünülüyor, ancak yavaş yavaş daha güvenilir ve kararlı hale gelecektir.

SOAP uzantısı, SOAP 1.1, SOAP 1.2 ve WSDL 1.1 spesifikasyonlarının büyük alt kümelerini uygular. Ana amaç, SOAP'ın RPC yeteneklerinden en iyi şekilde yararlanmaktır. WSDL, web hizmetlerinin uygulanmasını kolaylaştırmak için mümkün olan her yerde kullanılır.

İlk SOAP istemcisi

Basit bir SOAP istemcisinin yaratılışını göstermek için XMethods web sitesindeki "Gecikmeli Hisse Senedi Teklifi" demo hizmetini kullanıyoruz. PHP kodunu yazmaya başlamadan önce bu özel hizmet hakkında aşağıdaki bilgileri toplamamız gerekiyor:

  • Yöntem adı
  • Bu hizmetin bulunduğu URL
  • Yöntem SOAPAction başlık değeri
  • Yöntem ad alanı
  • Yöntem giriş ve çıkış parametrelerinin adları ve türleri

Şans eseri, tüm bu bilgilere http://www.xmethods.com/ adresindeki XMethods web sitesinde, hizmetin RPC profilinden ulaşılabilir:

Yöntem adı Alıntı Alın
Hizmet URL'si http://66.28.98.121:9090/soap
SABUNAksiyonu urn:xmethods-delayed-quotes#getQuote
Yöntem ad alanı urn:xmethods-gecikmeli-alıntılar
Giriş parametreleri Sembol (Dize)
Çıkış parametreleri Sonuç (kayan)

Örnek 1 (istemci1.php)

$client = new SoapClient(NULL,
sıralamak(
"konum" => "http://66.28.98.121:9090/soap",
"uri" =>
"stil" => SOAP_RPC,
"kullan" => SOAP_ENCODED
));

Yazdır($istemci -> __call (
/* SOAP yöntem adı */
"Alıntı al"
/* Seçenekler */
sıralamak(
yeni SoapParam(
/* Parametre değeri */
"ibm"
/* Parametre adı */
"sembol"
)),
/* Seçenekler */
sıralamak(
/* SOAP yöntemi ad alanı */
"uri" => "urn:xmethods-delayed-quotes",
/* Bir SOAP yöntemi için SOAPAction HTTP başlığı */
"sabunlaşma" => "urn:xmethods-delayed-quotes#getQuote"
)). "\N" );
?>

Gördüğünüz gibi bu basit sorunu çözmek oldukça fazla çalışma gerektiriyordu.

Neyse ki web hizmetleri, genellikle oldukça kullanışlı olan WSDL'yi kullanarak kendilerini müşterilere tanımlayabilir. "Gecikmeli Hisse Senedi Teklifi" hizmetine ilişkin WSDL, xmethods.com web sitesindeki bilgi sayfasında sunulmaktadır - http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl.

Burada aynı istemcinin bu WSDL belgesini kullanarak çalışacak şekilde yeniden yazılmış bir sürümü bulunmaktadır. Burada artık sunucu URI'sini, ad alanını, SOAPAction başlığını, kodlama yöntemini ve parametre türlerini belirtmemize gerek yok. Tüm bu bilgiler WSDL dosyasından alınmıştır.

Örnek 2 (client2.php)

$istemci = yeni
SoapClient(
"http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl"
);

Print($client -> getQuote("ibm" ));
?>

Bu şekilde biraz daha kolay, değil mi?

WSDL kullanırken ne gibi sorunlar ortaya çıkıyor? Bunu kullanmaya karşı olan tek argüman, herhangi bir prosedürün çağrılabilmesi için istemcinin sunucudan WSDL'yi okuması gerektiğidir ve web'de bu oldukça uzun zaman alabilir. Çalışmayı hızlandırmak için SOAP uzantısı aşağıdaki yapılandırma parametrelerini sağlar: sabun.wsdl_cache_enabled, sabun.wsdl_cache_dir ve sabun.wsdl_cache_ttl. Bunlar php.ini dosyasında veya ini_set() kullanılarak ayarlanabilir (bkz. Örnek 4). Varsayılan olarak WSDL önbelleğe alma etkindir ve WSDL dosyaları 1 gün boyunca önbelleğe alınır.

Burada php.ini dosyasının varsayılan değerlerin yer aldığı SOAP bölümü bulunmaktadır. Bunları php.ini dosyanıza kopyalayabilirsiniz.

[sabun]

Sabun. wsdl_cache_enabled = "1"
; WSDL önbelleğe almayı etkinleştirir veya devre dışı bırakır

Sabun. wsdl_cache_dir = "/tmp"
; SOAP'ın bulunduğu dizinin adını belirtir- uzantı önbelleğe alınmış dosyaları saklayacak

Sabun. wsdl_cache_ttl = "86400"
; (ömür ) zamanı ayarlar(saniyeler içinde) önbellekten hangi dosyalar kullanılabilir

İlk SOAP sunucusu

XMethods ile "Gecikmeli Hisse Senedi Kotesi" hizmetinin aynısını yapacak kendi SOAP web hizmetimizi yazmaya çalışalım.

Yapmamız gereken ilk şey, hizmetimizi müşterilerin anlayabileceği formatta açıklayan bir WSDL belgesi oluşturmaktır. Bunu yapmak için Xmethods web sitesinden alınan orijinal belgeyi biraz değiştirmeniz gerekecek, bu yüzden ona daha ayrıntılı bakarak başlayacağız.

Mesaj bölümü iki mesajı tanımlar. Bunlardan ilki, getQuote mesajını ileten ve sembol adlı tek satırlık bir parametreyi kabul eden getQuoteRequest'tir. İkinci mesaj, Result adlı tek bir kayan nokta değerini ileten getQuote isteğine verilen yanıt olan getQuoteResponse'dur.

portType bölümü, mesaj bölümünde açıklananlardan hangisinin istek için, hangisinin yanıt için kullanılacağını belirten getQuote adlı tek bir işlemi tanımlar.

Bağlama bölümü mesajın nasıl kodlanması ve iletilmesi gerektiğini tanımlar. Bu durumda SOAP kodlamasını kullanarak HTTP üzerinden RPC isteği göndereceğimizi belirtiyor. Ayrıca getQuote yöntemi için SOAPAction başlığının ad alanını ve değerini de tanımlar.

Son olarak hizmet bölümü, hizmetin bulunduğu URL'yi tanımlar.

Örnek 3 (stockquote.wsdl)


targetNamespace = "http://example.org/StockQuote"
xmlns:tns=" http://example.org/StockQuote "
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/">












taşıma = "http://schemas.xmlsoap.org/soap/http"/>



encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>


encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>








Not: WSDL önbelleğe alma varsayılan olarak etkindir. WSDL'nizi geliştirirken ve hata ayıklarken önbelleğe almayı devre dışı bırakmak daha iyidir.

Artık sunucumuzu oluşturmaya başlamanın zamanı geldi.

Öncelikle web'den gelen istekleri işleyecek bir getQuote() işlevi geliştireceğiz. Daha sonra, SoapServer sınıfının bir nesnesini oluşturacağız ve SoapServer::addFunction() yöntemini kullanarak fonksiyonumuzu ona ekleyeceğiz. Daha sonra göreceğiniz gibi, SoapServer() yapıcısının yalnızca tek bir parametresi vardır; hizmeti açıklayan WSDL belgesinin yolu.

Örnek 4 (sunucu1.php)

$tırnak işaretleri = dizi(
"ibm" => 98,42
);


küresel $ tırnaklar ;
return $tırnaklar [ $sembol ];
}

Ini_set ("soap.wsdl_cache_enabled", "0"); // WSDL önbelleğe almayı devre dışı bırak
$sunucu = new SoapServer("stockquote1.wsdl");
$sunucu -> addFunction("getQuote");
$sunucu -> tanıtıcı();
?>

SoapServer, WSDL olmadan istemciyle hemen hemen aynı şekilde çalışabilir, ancak bu seçeneği kullanmanın onu kullanmaya değer kılan hiçbir avantajı yoktur. Eğer yine de bu şekilde çalışmak istiyorsanız dönüş değerlerinin SoapParam ve SoapVar sınıflarının nesneleri olduğundan emin olmalısınız (ilk örnekte olduğu gibi.

İşte SOAP sunucumuza erişecek bir istemci. Önceki örnekle karşılaştırıldığında yalnızca WSDL konum bağlantısı eklenmiştir. "stockquote1.wsdl" dosyasının SOAP sunucusuyla aynı dizinde olduğu varsayılmaktadır.

Örnek 5 (client3.php)

$client = new SoapClient("stockquote1.wsdl");
print($client -> getQuote("ibm" ));
?>

İstemcimiz ve sunucumuzla ilgili temel sorunlar nelerdir?

Yeni başlayanlar için hataları ele almazlar. Sunucu kendisine iletilen sembol değişkeninin değerine uygun bir sonuç bulamadığında ne olur? SOAP'ın hata mesajları için özel bir mesaj formatı vardır - SoapFault.Böyle bir mesaj oluşturmak için sunucunun SoapFault nesnesini kullanarak bir istisna atması gerekir. SoapFault() yapıcısının ilk parametresi hata kodunu içeren bir dizedir, ikincisi ise hatanın açıklamasını içeren bir dizedir. İstemcinin SoapFault istisnalarını işleyecek şekilde yazılması gerekir.

İkinci olarak, web hizmetinin işlevselliğini bir PHP sınıfında kapsüllemek daha iyidir. Bu durumda global değişkenler kullanmamıza ve her SOAP yöntemini ayrı ayrı sunucuya eklememize gerek kalmayacak. Bunun yerine sınıfın tamamını ekleyebileceğiz ve onun tüm yöntemlerine SOAP aracılığıyla ulaşılabilecek. Burada istemci ve sunucunun uygun şekilde değiştirilmiş versiyonları verilmiştir.

Örnek 6 (sunucu2.php)

sınıf Alıntı Hizmeti(
özel $tırnak = array("ibm" => 98.42 );

fonksiyon getQuote ($sembol) (
if (isset($this -> tırnak işaretleri [ $sembol ])) (
return $this -> tırnak işaretleri [ $sembol ];
) başka (
yeni atmak
SoapFault("Sunucu", "Bilinmeyen Sembol "$sembol".");
}
}
}

$sunucu = new SoapServer("stockquote2.wsdl");
$sunucu -> setClass("QuoteService");
$sunucu -> tanıtıcı();
?>

Gördüğünüz gibi SoapServer nesnesini QuoteService sınıfına bağlamak için SoapServer::setClass() yöntemini kullandım.

Örnek 7 (client4.php)

$client = new SoapClient("stockquote2.wsdl");
denemek (
Eko "

\N" ; 
print($client -> getQuote("ibm" ));
yankı "\n";
print($client -> getQuote("microsoft"));
yankı "\n
\N" ;
) catch (SoapFault $istisna) (
echo $istisna;
}
?>

İçinde ne var?

SOAP mesajlarının formatını anlamak istiyorsanız veya bir SOAP istemcisinin hatalarını kendiniz ayıklamak istiyorsanız bu bölüm tam size göre.

İlk örnekte gördüğünüz gibi, SoapClient() yapıcısı ikinci parametresi olarak bir ilişkisel diziyi alır. Bu dizi ile sunucudaki çeşitli seçenekleri çağırabiliriz.

Bunlardan ikisine bakalım:

  • izleme - istemcinin SOAP isteklerini ve yanıtlarını kaydetmesine olanak tanır (varsayılan olarak devre dışıdır).
  • istisnalar - istemcinin istisna mekanizmasını kontrol etmesine olanak tanır (varsayılan olarak etkindir).

Aşağıdaki SOAP istemci örneğine bakalım. Bu, istemci ile sunucu arasında tam olarak neyin aktarıldığını gösteren, Örnek 5'teki istemcinin genişletilmiş halidir. Bu bilgiyi elde etmek için __getLastRequest() ve __getLastResponse() yöntemleri kullanılır.

Örnek 8 (client5.php)

$istemci = new SoapClient("stockquote1.wsdl", dizi(
"iz" => 1,
"istisnalar" => 0));
$client -> getQuote("ibm");
Yazdır "

\N" ; 
"Sorgu:\n" yazdır. htmlspecialchars ($client -> __getLastRequest()) . "\N" ;
"Cevap:\n" yazdır. htmlspecialchars($client -> __getLastResponse()). "\N" ;
Yazdır "
" ;
?>

İşte betiğin çıktısı. Anlaşılmasını kolaylaştırmak için biraz değiştirildi.

Rica etmek:



xmlns:xsd="http://www.w3.org/2001/XMLSchema"

SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">


IBM


Cevap:


xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:xmethods-delayed-quotes"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">


98.42


PHP için diğer SOAP uygulamaları

Hepsi C ile değil PHP ile yazılmıştır.

Özet

Bu yazımda SOAP eklentisinin sadece temel fonksiyonlarını anlattım. Aslında çok daha fazlasını yapabilir, ancak tüm yeteneklerini kısa bir makalede göstermek kesinlikle imkansızdır. İşte ana olanların bir listesi:

  1. Karmaşık veri türleri (diziler, nesneler) desteği
  2. SOAP başlık desteği
  3. SOAP 1.1 ve SOAP 1.2 için dinamik destek

Belki sonraki makalelerde daha ayrıntılı olarak ele alınacaktır.

SOAP uzantısına ilişkin ayrıntılı belgeler http://www.php.net/manual/en/ref.soap.php adresinde bulunmaktadır.

Bu uzantının geliştirilmesi henüz ilk aşamalarında olduğundan geri bildirimleriniz eklentinin daha kararlı, güvenilir, kullanışlı ve hızlı olmasına yardımcı olacaktır. Lütfen kullanırken karşılaştığınız sorunları http://bugs.php.net/ adresine bildirin.

Bağlantılar

yazar hakkında

PHP'de bir SOAP web hizmeti oluşturmak için öncelikle yerel bir HTTP sunucusunun yanı sıra PHP'yi de kurup yapılandırmanız gerekir. Bu projede Apache ve PHP HTTP sunucusunun hızlı kurulumuna olanak sağlayan XAMP paketi kullanıldı.

Ayrı olarak Apache ve PHP yapılandırma dosyalarında da değişiklik yapmanız gerekir.

Apache HTTP sunucusu yapılandırma dosyası httpd.conf'da aşağıdaki kod parçasını bulmanız gerekir:

PHP betiklerini yerel bir sunucuda çalıştırmak için, bunları Apache sunucusunun kök dizininde, varsayılan olarak Apache kök klasöründeki htdocs klasöründe saklamanız gerekir.

Sitenin kök dizinini değiştirmek için httpd.conf dosyasında aşağıdaki satırda değişiklik yapmanız gerekmektedir:

PHP desteğini etkinleştirmek için httpd.conf dosyasına aşağıdaki satırları eklemelisiniz:


Apache HTTP sunucusunu başlatmak için konsol komutlarını veya Apache'nin durumunu yönetmenize ve yapılandırmanıza olanak tanıyan XAMMP kontrol panelini kullanabilirsiniz.

Bu yardımcı programın görünümü Şekil 2'de gösterilmektedir.

Şekil 2. - XAMMP Kontrol Paneli yardımcı programı:


SOAP web hizmeti oluşturmak için uygulamanın istemci ve sunucu taraflarını uygulayan PHP belgelerinin yanı sıra web hizmetini açıklayan bir WSDL sayfası yazmanız gerekir.

İstemciye iki sayı üzerinde yapılan aritmetik işlemin sonucunu döndüren bir web hizmeti sağlayan bir web hizmeti oluşturalım. Giriş elemanları, müşteri tarafından belirlenen iki sayının yanı sıra bir aritmetik işlemi tanımlayan sembolik bir değişkendir.

İstemci tarafı iki PHP belgesi tarafından uygulanır. Form.php dosyasında öğeyi kullanarak

kullanıcının veri girdiği formu açıklar. Form özellikleri, formdan bilgi çıkarmak ve onu bir PHP dosyasına aktarmak için kullanılan POST yöntemini içerir. Bu durumda kullanıcının girdiği veriler afqk code.php dosyasına aktarılır. Elementler Veri girmek için metin alanlarını ve bir düğmeyi tanımlayın, tıklandığında veriler code.php dosyasına aktarılır.

form.php dosyasını uygulayan kod pasajı aşağıdadır:


Code.php dosyasında istemci sınıfının bir örneği oluşturulur ve kullanıcı tarafından girilen veriler alınır ve bir SOAP mesajı olarak sunucuya gönderilir. İstemci sınıfının bir örneğinin oluşturulmasını uygulayan bir kod parçası aşağıda verilmiştir:

Bu parçada, SOAP mesajını cacl.wsdl yapılandırma dosyasına uygun olarak yürüten SoapClient sınıfı $client'in bir örneği oluşturulur.

Code.php dosyası ayrıca $a, $b, $action değişkenlerine form.php'den alınan verileri saklayan $_POST ilişkisel dizisinin üyelerinin değerlerini atar.

Bu işlemleri uygulayan bir kod parçası aşağıda verilmiştir:

Burada getCalcEntry(), WSDL dosyasında açıklanan işlemdir.

Bu web servisinde sunucu kısmının rolünü calc-server.php dosyası üstlenir.

Bu dosya getCalcEntry işlevini bildirir ve çağırır.

Bu fonksiyon $action değişkeninin değerini kontrol eder ve buna göre $a ve $b değişkenleri üzerinde işlem yaparak sonucu $c değişkenine yazar. Bu kod parçasında addFunction() yöntemi, uzak istemcinin getCalcentry işlevine erişim sağlar. Handle() yöntemi SOAP isteğini işler, gerekli işlevleri çağırır ve SOAP yanıtını gönderir. Bu fonksiyonu gerçekleştiren kod parçası aşağıda verilmiştir:


Açıklama dosyası calc.wsdl, bu SOAP web hizmetinin çalışmasında önemli bir rol oynar.

Bu dosya SOAP mesajlarının ana parametrelerini tanımlar. Bunu uygulamaktan sorumlu kod pasajı aşağıda verilmiştir:


Bu parçadaki unsurlar getCalcRequest ve getCalcResponse - sırasıyla SOAP isteği ve SOAP yanıtı. İç içe geçmiş öğeler aktarılan değişkenlerin adlarını ve türlerini tanımlar. PHP'deki dinamik yazma sayesinde örtülü olarak sayılara dönüştürülecek dizeleri (type string) iletmenin mümkün olduğunu belirtmek gerekir. WSDL dosyasının bir diğer önemli unsuru, eleman tarafından gerçekleştirilen web hizmeti arayüzünün açıklamasıdır.

Bu parçadaki eleman iki eylemden oluşan belirli bir getCalcEntry hizmetini açıklar:

  • - ilk eylem getCalcRequest mesajın gönderilmesini temsil eder;
  • - ikinci eylem getCalcResponse - bir yanıt alma.

Bir web hizmetini yerel bir sunucuda başarıyla çalıştırmak için şunları yapmalısınız:

  • 1) Apache sunucusunun kök dizininde dağıtılmış uygulama için ayrı bir dizin oluşturun. form.php, code.php, calc-server.php ve calc.wsdl dosyalarını içine yerleştirin;
  • 2) Konsolu veya XAMMP kontrol panelini kullanarak Apache'yi başlatın;
  • 3) Tarayıcının adres çubuğuna web hizmeti istemcisinin adresini girin;
  • 4) Metin alanlarına verileri girin ve Hesapla düğmesine tıklayın;
  • 5) Sonuç olarak, tarayıcı sekmesinde görüntülenen hesaplama sonucunu içeren bir PHP sayfası açılacaktır.

Şekil 3. - Değiştirilen web hizmetinin sonucu:


SOAP'ın çalışmasını daha ayrıntılı olarak ele almak için, code.php dosyasının kodunu, en son SOAP mesajlarının (istek ve yanıt) listesi, hesaplama sonucuyla birlikte tarayıcıda görüntülenecek şekilde değiştiriyoruz.

Bu işlevleri gerçekleştiren bir kod parçası aşağıda gösterilmiştir:


web sunucusu programlama

Bu parça sınıfın standart sistem yöntemlerini içerir:

SOAP mesajlarının metnini döndürme. Bu şekilde alınan SOAP mesajları incelendiğinde client ile sunucu arasındaki veri alışverişi açıkça görülmektedir. İstenildiği takdirde veriler aşağıdaki kod parçasında yer alır. Bu parça, elementi içeren SOAP zarfının gövdesini içerir. , bir web hizmetini açıklamaktadır.


Aktarılan değişkenlerin değerlerini ve veri türlerini saklayan öğeler içerir. Sunucuya 5 ve 3 rakamlarının değerleri ve bunlar üzerinde gerçekleştirilen çıkarma işleminin sembolü gönderilir.

Cevap için benzer bir kod pasajı aşağıdadır:


Bu kod parçasında istemciye gönderilen çıkarma sonucunun değerini görebilirsiniz - 2.

Herkese selam!
Öyle oldu ki yakın zamanda web hizmetleri geliştirmeye başladım. Ancak bugünkü konu benimle ilgili değil, SOAP 1.2 protokolünü temel alarak kendi XML Web Servisimizi nasıl yazabileceğimizle ilgili.

Umarım konuyu okuduktan sonra şunları yapabileceksiniz:

  • bir web uygulamasının kendi sunucu uygulamasını yazın;
  • bir web uygulamasının kendi istemci uygulamasını yazın;
  • kendi web hizmeti açıklamanızı (WSDL) yazın;
  • aynı türdeki verilerin istemci dizilerini sunucuya gönderin.

Tahmin edebileceğiniz gibi, tüm sihir PHP ve yerleşik SoapClient ve SoapServer sınıfları kullanılarak yapılacak. Tavşanımız SMS mesajı göndermeye yönelik bir hizmet olacaktır.

1 Sorun bildirimi

1.1 Sınırlar

Başlangıçta konunun sonunda elde edeceğimiz sonuçla ilgilenmeyi öneriyorum. Yukarıda da açıkladığımız gibi SMS mesaj göndermek için bir servis yazacağız, daha doğrusu SOAP protokolü üzerinden farklı kaynaklardan mesaj alacağız. Bundan sonra sunucuya hangi biçimde ulaştıklarını ele alacağız. Mesajların sağlayıcıya daha fazla teslim edilmek üzere sıraya alınması süreci maalesef birçok nedenden dolayı bu yazının kapsamı dışındadır.

1.2 Hangi verileri değiştireceğiz?

Harika, sınırlara karar verdik! Atılması gereken bir sonraki adım, sunucu ve istemci arasında hangi veri alışverişini yapacağımıza karar vermektir. Bu konuda çok uzun süre kılları ayırmamanızı ve ana soruları hemen kendiniz cevaplamanızı öneririm:

  • Bir aboneye SMS mesajı göndermek için sunucuya hangi minimum verilerin gönderilmesi gerekir?
  • İstemcinin ihtiyaçlarını karşılamak için sunucudan hangi minimum veriler gönderilmelidir?

İçimden bir ses bunun için aşağıdakileri göndermeniz gerektiğini söylüyor:

  • cep telefonu numarası ve
  • SMS mesajının metni.

Prensip olarak, bu iki özellik göndermek için yeterlidir, ancak doğum günü tebriklerini içeren bir SMS'in sabah saat 3'te veya 4'te size geleceğini hemen hayal ediyorum! Şu anda beni unutmadıkları için herkese çok minnettar olacağım! Bu nedenle sunucuya da göndereceğiz ve

  • SMS mesajının gönderilme tarihi.

Sunucuya göndermek istediğim bir sonraki şey:

  • Mesaj tipi.

Bu parametre zorunlu değildir, ancak patronumuza haberlerimizden kaç müşterimizi "memnun ettiğimizi" hızlıca söylememiz ve ayrıca bu konuyla ilgili bazı güzel istatistikler çizmemiz gerekirse, bizim için çok yararlı olabilir.

Ama yine de bir şeyi unuttum! Biraz daha düşünürsek, istemcinin sunucuya aynı anda hem bir SMS mesajı hem de birden fazla mesaj gönderebileceğini belirtmekte fayda var. Başka bir deyişle, bir veri paketi birden sonsuza kadar mesaj içerebilir.

Sonuç olarak, bir SMS mesajı göndermek için aşağıdaki verilere ihtiyacımız var:

  • Cep telefonu numarası,
  • SMS mesaj metni,
  • SMS mesajının aboneye gönderilme zamanı,
  • mesaj tipi.

Birinci soruyu yanıtladık, şimdi ikinci soruyu yanıtlamamız gerekiyor. Ve belki de biraz ortalığı karıştırmama izin veririm. Bu nedenle, sunucudan yalnızca anlamı aşağıdaki anlama gelen Boolean verilerini göndereceğiz:

  • DOĞRU – paket sunucuya başarıyla ulaştı, kimlik doğrulamayı geçti ve SMS sağlayıcısına gönderilmek üzere sıraya alındı
  • YANLIŞ – diğer tüm durumlarda

Bu, sorun bildiriminin açıklamasını tamamlıyor! Ve son olarak işin eğlenceli kısmına geçelim - bu SABUN'un ne tür tuhaf bir canavar olduğunu bulalım!

2 SABUN Nedir?

Genel olarak, başlangıçta SOAP'ın ne olduğu hakkında hiçbir şey yazmayı planlamadım ve kendimi gerekli spesifikasyonları içeren w3.org web sitesine olan bağlantıların yanı sıra Wikipedia bağlantılarıyla sınırlamak istedim. Ancak en sonunda bu protokol hakkında kısa bir not yazmaya karar verdim.

Ve hikayeme, bu veri alışverişi protokolünün, antipodu REST (Temsili Durum Transferi) olan RPC (Uzaktan Prosedür Çağrısı) paradigmasına dayanan bir protokol alt kümesine ait olduğu gerçeğiyle başlayacağım. Bununla ilgili daha fazla bilgiyi Vikipedi'de okuyabilirsiniz; makalelere bağlantılar konunun en sonundadır. Bu yazılardan şunu anlamamız gerekiyor: “RPC yaklaşımı, az sayıda ağ kaynağının çok sayıda yöntem ve karmaşık bir protokolle kullanılmasına olanak tanıyor. REST yaklaşımıyla yöntemlerin sayısı ve protokol karmaşıklığı kesinlikle sınırlıdır, bu da bireysel kaynakların sayısının büyük olabileceği anlamına gelir." Yani bizimle ilgili olarak bu, RPC yaklaşımı durumunda sitede her zaman hizmete bir giriş (bağlantı) olacağı ve verilerle birlikte ilettiğimiz gelen verileri işlemek için hangi prosedürün çağrılacağı anlamına gelir. Sitemizde REST yaklaşımı ile her biri yalnızca belirli verileri kabul eden ve işleyen çok sayıda giriş (bağlantı) bulunmaktadır. Eğer okuyan biri bu yaklaşımların farkını daha basit bir şekilde nasıl açıklayacağını biliyorsa, yorumlara yazmayı unutmayın!

SOAP hakkında bilmemiz gereken bir sonraki şey, bu protokolün aktarımla aynı XML'i kullanmasıdır ki bu bir yandan çok iyidir, çünkü Cephaneliğimiz, sunucu tarafından alınan verilerin otomatik olarak doğrulanmasına olanak tanıyan, bir XML belgesinin yapısını açıklayan bir dil olan XML-Şema adlı bu işaretleme dilini temel alan bir teknoloji yığınının tam gücünü hemen içerir (teşekkürler Wikipedia!) müşterilerden.

Artık SOAP'ın uzaktan prosedür çağrılarını uygulamak için kullanılan bir protokol olduğunu ve aktarım olarak XML'i kullandığını biliyoruz! Wikipedia'daki makaleyi okursanız, oradan bunun yalnızca HTTP ile kombinasyon halinde değil, herhangi bir uygulama düzeyindeki protokol üzerinden kullanılabileceğini de öğrenebilirsiniz (maalesef bu konuda yalnızca HTTP üzerinden SOAP'ı ele alacağız). Ve tüm bunların en çok neyi hoşuma gidiyor biliyor musun? Tahmin yoksa bir ipucu vereceğim - SABUN!... Hala tahmin yok mu?... Wikipedia'daki makaleyi okuduğunuzdan emin misiniz?... Genel olarak size daha fazla işkence yapmayacağım. Bu nedenle doğrudan cevaba geçeceğim: “SOAP (İngilizce Basit Nesne Erişim Protokolünden - basit protokol nesnelere erişim; spesifikasyon 1.2'ye kadar)". Bu satırdaki en dikkat çekici şey italik yazılmış olmasıdır! Tüm bunlardan ne gibi sonuçlar çıkardığınızı bilmiyorum, ancak şunu görüyorum - bu protokol hiçbir şekilde "basit" olarak adlandırılamayacağından (ve görünüşe göre w3 bile buna katılıyor), o zaman 1.2 sürümünden itibaren şifresinin çözülmesi bir şekilde durduruldu. ! Ve SABUN olarak tanındı, sadece SABUN, nokta.

Tamam, lütfen kusura bakmayın, konuyu biraz kenara çektik. Daha önce de yazdığım gibi aktarım olarak XML kullanılıyor ve istemci ile sunucu arasında dolaşan paketlere SOAP zarfları adı veriliyor. Zarfın genel yapısını dikkate alırsanız size çok tanıdık gelecektir çünkü... HTML sayfasının işaretlemesine benzer. Bir ana bölümü var - Zarf bölümleri içeren Başlık Ve Vücut, veya Arıza. İÇİNDE Vücut veri iletilir ve zarfın zorunlu bir bölümüdür. Başlıkİsteğe bağlı. İÇİNDE Başlık yetkilendirme veya web hizmeti prosedürlerinin giriş verileriyle doğrudan ilgili olmayan diğer veriler iletilebilir. Hakkında Arıza Herhangi bir hata durumunda sunucudan istemciye gelmesi dışında söylenecek özel bir şey yok.

SOAP protokolü hakkındaki inceleme hikayem burada bitiyor (istemcimiz ve sunucumuz nihayet onları birbirlerine çalıştırmayı öğrendiğinde zarfların kendilerine ve yapılarına daha ayrıntılı olarak bakacağız) ve yeni bir hikaye başlıyor - SOAP arkadaşı hakkında WSDL(Web Hizmetleri Açıklama Dili). Evet, evet çoğumuzu bu protokol üzerinde API'mizi uygulamaya çalışmaktan bile korkutan şey budur. Sonuç olarak taşıma aracı olarak JSON ile tekerleğimizi genellikle yeniden icat ediyoruz. Peki WSDL nedir? WSDL, XML dilini (c) Wikipedia'yı temel alarak web hizmetlerini tanımlayan ve bunlara erişen bir dildir. Eğer bu tanım size bu teknolojinin tüm kutsal anlamını açıklamıyorsa, o zaman onu kendi kelimelerimle anlatmaya çalışacağım!

WSDL, müşterilerimizin sunucuyla normal şekilde iletişim kurmasına olanak sağlayacak şekilde tasarlanmıştır. Bunun için “*.wsdl” uzantılı dosyada aşağıdaki bilgiler anlatılmaktadır:

  • Hangi ad alanları kullanıldı?
  • Hangi veri şemaları kullanıldı?
  • Web hizmeti istemcilerden ne tür mesajlar bekliyor?
  • Hangi verinin hangi web servis prosedürlerine ait olduğu,
  • Web hizmeti hangi prosedürleri içerir?
  • Müşteri web servis prosedürlerini nasıl çağırmalı,
  • Müşteri çağrıları hangi adrese gönderilmelidir?

Gördüğünüz gibi bu dosya tüm web hizmetidir. İstemcide WSDL dosyasının adresini belirterek herhangi bir web hizmeti hakkında her şeyi bileceğiz! Sonuç olarak, web hizmetinin nerede bulunduğu hakkında kesinlikle hiçbir şey bilmemize gerek yok. Bilmeniz gereken tek şey WSDL dosyasının konumu! Yakında SOAP'ın Rus atasözlerinde anlatıldığı kadar korkutucu olmadığını öğreneceğiz.

3 XML Şemasına Giriş

Artık SOAP'ın ne olduğu, içinde ne olduğu hakkında çok şey biliyoruz ve onu çevreleyen teknoloji yığınına dair genel bir bakışa sahibiz. Her şeyden önce SOAP, istemci ile sunucu arasındaki etkileşimin bir yöntemi olduğundan ve bunun için aktarım olarak XML işaretleme dili kullanıldığından, bu bölümde XML şemaları kullanılarak otomatik veri doğrulamanın nasıl gerçekleştiğini biraz anlayacağız.

Diyagramın ana görevi, işleyeceğimiz verilerin yapısını tanımlamaktır. XML şemalarındaki tüm veriler aşağıdakilere bölünmüştür: basit(skaler) ve karmaşık(yapılar) türleri. Basit türler aşağıdaki türleri içerir:

  • astar,
  • sayı,
  • Boole değeri,
  • Tarihi.

İçinde hiçbir uzantı olmayan çok basit bir şey. Antipodları karmaşık karmaşık türlerdir. Karmaşık türün herkesin aklına gelen en basit örneği nesnelerdir. Örneğin bir kitap. Kitap özelliklerden oluşur: yazar, İsim, fiyat, ISBN numarası vesaire. Ve bu özellikler sırasıyla basit türler veya karmaşık olanlar olabilir. XML şemasının görevi de bunu anlatmaktır.

Fazla ileri gitmemenizi ve SMS mesajımız için bir XML şeması yazmanızı öneririm! SMS mesajının xml açıklaması aşağıdadır:

71239876543 Deneme mesajı 2013-07-20T12:00:00 12

Karmaşık tip diyagramımız şöyle görünecek:

Bu girdi şu şekildedir: Bir değişkenimiz var " İleti" tip " İleti" ve " adında karmaşık bir tür var İleti" sıralı bir dizi öğeden oluşur " telefon" tip sicim, « metin" tip sicim, « tarih" tip tarihSaat, « tip" tip ondalık. Bu türler basittir ve şema açıklamasında zaten tanımlanmıştır. Tebrikler! Az önce ilk XML Şemamızı yazdık!

Bence elementlerin anlamı " eleman" Ve " karmaşık Tür"Her şey sizin için aşağı yukarı netleşti, bu yüzden artık bunlara odaklanmayacağız ve doğrudan besteci unsuruna geçelim" sekans" Besteci öğesini kullandığımızda " sekans“İçerdiği elemanların her zaman şemada belirtilen sırada yer alması gerektiğini ve hepsinin zorunlu olduğunu size bildiririz. Ama umutsuzluğa kapılmayın! XML şemalarında iki besteci öğesi daha vardır: " seçenek" Ve " Tümü" Besteci " seçenek"İçinde listelenen unsurlardan birinin ve bestecinin olması gerektiğini duyurur" Tümü» – listelenen öğelerin herhangi bir kombinasyonu.

Hatırlayacağınız gibi konunun ilk bölümünde bir pakette birden sonsuza kadar SMS mesajının iletilebileceği konusunda anlaşmıştık. Bu nedenle, bu tür verilerin XML şemasında nasıl bildirildiğini anlamayı öneriyorum. Genel paket yapısı şöyle görünebilir:

71239876543 Test mesajı 1 2013-07-20T12:00:00 12 71239876543 Test mesajı N 2013-07-20T12:00:00 12

Böyle karmaşık bir türün diyagramı şöyle görünecektir:

İlk blok, “karmaşık türün tanıdık bildirimini içerir” İleti" Fark ettiyseniz, " içinde yer alan her basit türde İleti", yeni açıklayıcı özellikler eklendi" dkOluşur" Ve " maxOccurs" Adından da tahmin edebileceğiniz gibi, ilk ( dkOluşur), bu dizinin " türünde en az bir öğe içermesi gerektiğini belirtir. telefon», « metin», « tarih" Ve " tip", bir sonraki ( maxOccurs) niteliği bize dizimizde böyle bir öğenin en fazla olduğunu bildirir. Sonuç olarak, herhangi bir veri için kendi şemalarımızı yazdığımızda, bunları nasıl yapılandıracağımız konusunda bize en geniş seçenek sunulur!

Diyagramın ikinci bloğu "öğesini bildirir" mesajListesi" tip " Mesaj Listesi" Şu açık ki" Mesaj Listesi"en az bir öğe içeren karmaşık bir türdür" İleti", ancak bu tür öğelerin maksimum sayısı sınırlı değildir!

4 WSDL'nizi yazın

WSDL'nin web hizmetimiz olduğunu hatırlıyor musunuz? Umarım hatırlarsın! Biz bunu yazarken küçük web servisimiz onun üzerinde çalışacaktır. Bu nedenle ortalığı karıştırmamanızı öneririm.

Genel olarak bizim için her şeyin doğru çalışması için istemciye doğru MIME türüne sahip bir WSDL dosyası aktarmamız gerekiyor. Bunun için web sunucunuzu buna göre yapılandırmanız yani “*.wsdl” uzantılı dosyalar için MIME tipini aşağıdaki satıra ayarlamanız gerekmektedir:

Uygulama/wsdl+xml

Ancak pratikte genellikle HTTP başlığını PHP aracılığıyla gönderdim " metin/xml»:

Header("Content-Type: text/xml; karakter kümesi=utf-8");

ve her şey harika çalıştı!

Basit web hizmetimizin oldukça etkileyici bir açıklamaya sahip olacağı konusunda sizi hemen uyarmak istiyorum, bu yüzden paniğe kapılmayın, çünkü... Metnin çoğu zorunlu sudur ve bir kez yazdıktan sonra onu bir web hizmetinden diğerine sürekli olarak kopyalayabilirsiniz!

WSDL XML olduğundan, bunu doğrudan ilk satıra yazmanız gerekir. Dosyanın kök öğesi her zaman " olarak adlandırılmalıdır tanımlar»:

Tipik olarak WSDL 4-5 ana bloktan oluşur. İlk blok bir web servisinin tanımı, diğer bir deyişle giriş noktasıdır.

Burada şöyle bir hizmetimiz olduğu yazıyor: " SMS Hizmeti" Prensip olarak, WSDL dosyasındaki tüm adlar sizin tarafınızdan istediğiniz şekilde değiştirilebilir, çünkü kesinlikle hiçbir rol oynamazlar.

Bundan sonra bunu web hizmetimizde duyuruyoruz " SMS Hizmeti" adında bir giriş noktası ("bağlantı noktası") var " SmsServicePort" İstemcilerden sunucuya gelen tüm istekler bu giriş noktasına gönderilecektir. Ve “ öğesinde belirtin adres» İstekleri kabul edecek işleyici dosyasına bağlantı.

Web hizmetini tanımladıktan ve onun için giriş noktasını belirledikten sonra, desteklenen prosedürleri buna bağlamamız gerekir:

Bunun için hangi işlemlerin hangi formda çağrılacağını listeler. Onlar. liman için" SmsServicePort"adın altında bir bağlama tanımlandı" SmsServiceBinding", bir çağrı türüne sahip" rpc"ve iletim protokolü olarak HTTP kullanılıyor. Böylece HTTP üzerinden RPC çağrısı yapacağımızı burada belirtmiş olduk. Bundan sonra hangi prosedürleri açıklayacağız ( operasyon) web hizmetinde desteklenir. Yalnızca tek bir prosedürü destekleyeceğiz – “ SMS gönder" Bu prosedür sayesinde harika mesajlarımız sunucuya gönderilecektir! İşlem ilan edildikten sonra verilerin hangi formda iletileceğinin belirtilmesi gerekmektedir. Bu durumda standart SOAP zarflarının kullanılacağı belirtiliyor.

Bundan sonra prosedürü mesajlara bağlamamız gerekiyor:

Bunu yapmak için bağlamamızın " türünde olduğunu belirtiyoruz. SmsServicePortType" ve öğenin içinde " bağlantı noktası türü"Aynı türdeki isimle prosedürlerin mesajlara bağlanmasını belirtiyoruz. Ve böylece, gelen mesaj (istemciden sunucuya) “ SmsTalebi gönder" ve giden (sunucudan istemciye) " SmsYanıt gönder" WSDL'deki tüm adlar gibi, gelen ve giden mesajların adları da isteğe bağlıdır.

Şimdi mesajların kendisini tanımlamamız gerekiyor; giren ve çıkan:

Bunu yapmak için öğeleri ekliyoruz " İleti"isimlerle" SmsTalebi gönder" Ve " SmsYanıt gönder" sırasıyla. Bunlarda girdinin, yapısı veri türüne karşılık gelen bir zarf olması gerektiğini belirtiyoruz " Rica etmek" Bundan sonra sunucudan veri türünü içeren bir zarf döndürülür - “ Cevap».

Şimdi biraz yapmamız gerekiyor; bu türlerin açıklamalarını WSDL dosyamıza ekleyin! Peki WSDL'nin gelen ve giden verileri nasıl tanımladığını düşünüyorsunuz? Sanırım her şeyi uzun zaman önce anladınız ve bunu XML şemalarını kullanarak kendinize söylediniz! Ve kesinlikle haklı olacaksın!

Bizi tebrik edebilirsiniz! İlk WSDL'miz yazıldı! Ve hedefimize ulaşmaya bir adım daha yaklaştık.
Daha sonra, kendi dağıtılmış uygulamalarımızı geliştirmemiz için PHP'nin bize neler sağladığına bakacağız.

5 İlk SOAP sunucumuz

Daha önce PHP'de bir SOAP sunucusu oluşturmak için yerleşik SoapServer sınıfını kullanacağımızı yazmıştım. Diğer tüm eylemlerin benimkiyle aynı şekilde gerçekleşmesi için PHP'nizde biraz değişiklik yapmanız gerekecek. Daha da kesin olmak gerekirse, “php-soap” uzantısının kurulu olduğundan emin olmanız gerekir. Bunu web sunucunuza nasıl kuracağınızı resmi PHP web sitesinde okumak en iyisidir (referans listesine bakın).

Her şey yüklenip yapılandırıldıktan sonra hostinginizin kök klasöründe bir dosya oluşturmamız gerekecek " smsservice.php» aşağıdaki içeriğe sahip:

setClass("SoapSmsGateWay"); //Sunucuyu başlat $sunucu->tanımlayıcı();

Umarım çizginin üstünü “ini_set” fonksiyonu ile açıklamaya gerek yoktur. Çünkü orada sunucudan istemciye hangi HTTP başlıklarını göndereceğimiz belirlenir ve ortam yapılandırılır. “ini_set” doğrultusunda WSDL dosyasının önbelleğe alınmasını devre dışı bırakıyoruz, böylece dosyadaki değişikliklerimiz istemcide anında etkili olur.

Şimdi sunucuya geliyoruz! Gördüğünüz gibi SOAP sunucusunun tamamı yalnızca üç satır alıyor! İlk satırda SoapServer nesnesinin yeni bir örneğini oluşturuyoruz ve web hizmetinin WSDL açıklamamızın adresini yapıcısına aktarıyoruz. Artık hostingin kökünde açıklayıcı isimde bir dosyada yer alacağını biliyoruz. smsservice.wsdl.php" İkinci satırda SOAP sunucusuna client'tan gelen zarfı işleyebilmesi ve zarfın yanıtla birlikte geri dönebilmesi için hangi sınıfın çekilmesi gerektiğini söylüyoruz. Tahmin edebileceğiniz gibi, tek yöntemimiz bu sınıfta anlatılacak SMS gönder. Üçüncü satırda sunucuyu başlatıyoruz! İşte bu, sunucumuz hazır! Bununla hepimizi tebrik ediyorum!

Şimdi WSDL dosyasını oluşturmamız gerekiyor. Bunu yapmak için, önceki bölümden içeriğini kopyalayabilir veya özgürce davranıp biraz "şablon" oluşturabilirsiniz:

"; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http://http:// schemas.xmlsoap.org/wsdl/http/" name = "SmsWsdl" xmlns = "http://schemas.xmlsoap.org/wsdl/"> /"> /smsservice.php" />

Bu aşamada ortaya çıkan sunucudan tamamen memnun olmalıyız çünkü Kendisine gelen zarfları kayıt altına alıp ardından gelen verileri sakin bir şekilde analiz edebiliyoruz. Sunucudan herhangi bir şey alabilmemiz için bir istemciye ihtiyacımız var. O halde hadi konuya geçelim!

6 SOAP istemcisi yolda

Öncelikle clienti yazacağımız bir dosya oluşturmamız gerekiyor. Her zamanki gibi, onu ana bilgisayarın kökünde oluşturacağız ve adını vereceğiz " client.php"ve içine şunları yazacağız:

mesajListesi = yeni MesajListesi(); $req->messageList->message = yeni Mesaj(); $req->messageList->message->telefon = "79871234567"; $req->messageList->message->text = "Mesaj 1'i test edin"; $req->messageList->message->date = "2013-07-21T15:00:00.26"; $req->messageList->message->type = 15; $client = new SoapClient("http://($_SERVER["HTTP_HOST"])/smsservice.wsdl.php", array("soap_version" => SOAP_1_2)); var_dump($client->sendSms($req));

Nesnelerimizi tanımlayalım. WSDL'yi yazdığımızda sunucuya gelen zarf için üç varlık tanımlıyordu: Rica etmek, Mesaj Listesi Ve İleti. Buna göre sınıflar Rica etmek, Mesaj Listesi Ve İleti bu varlıkların PHP betiğimizdeki yansımalarıdır.

Nesneleri tanımladıktan sonra bir nesne oluşturmamız gerekir ( $talep), sunucuya göndereceğiz. Bundan sonra bizim için en değerli iki satır geliyor! SABUN müşterimiz! İster inanın ister inanmayın, bu, sunucumuzun istemciden mesaj almaya başlaması ve sunucumuzun bunları başarıyla alıp işlemesi için yeterlidir! Bunlardan ilkinde SoapClient sınıfının bir örneğini oluşturup WSDL dosyasının konumunun adresini yapıcısına aktarıyoruz ve parametrelerde SOAP protokolü sürüm 1.2'yi kullanarak çalışacağımızı açıkça belirtiyoruz. Bir sonraki satırda yöntemi çağırıyoruz SMS gönder nesne $müşteri ve sonucu anında tarayıcıda görüntüleyin.
Hadi çalıştıralım ve sonunda ne elde ettiğimizi görelim!

Aşağıdaki nesne sunucudan bana döndürüldü:

Object(stdClass) public "status" => boolean true

Ve bu harika, çünkü... Artık sunucumuzun çalıştığından ve yalnızca çalışmakla kalmayıp aynı zamanda istemciye bazı değerleri de döndürebildiğinden eminiz!

Şimdi sunucu tarafında ihtiyatlı bir şekilde tuttuğumuz loga bakalım! İlk bölümünde sunucuya ulaşan ham verileri görüyoruz:

79871234567 Test mesajı 1 2013-07-21T15:00:00.26 15

Bu zarf. Artık neye benzediğini biliyorsun! Ancak ona her zaman bakmakla ilgilenmemiz pek olası değil, bu yüzden nesneyi günlük dosyasından seri durumdan çıkaralım ve her şeyin yolunda olup olmadığına bakalım:

Object(stdClass) public "messageList" => object(stdClass) public "mesaj" => object(stdClass) public "telefon" => string "79871234567" (uzunluk=11) public "text" => string "Test mesajı 1 " (uzunluk=37) public "date" => string "2013-07-21T15:00:00.26" (uzunluk=22) public "type" => string "15" (uzunluk=2)

Gördüğünüz gibi nesne doğru bir şekilde seri durumdan çıkarıldı ve bunun için hepimizi tebrik etmek istiyorum! Bundan sonra bizi daha ilginç bir şey bekliyor! Yani, istemciye sunucuya yalnızca bir SMS mesajı değil, bütün bir paket (daha kesin olmak gerekirse üç) göndereceğiz!

7 Karmaşık nesneleri gönderme

Bir sürü mesajı sunucuya tek bir pakette nasıl aktarabileceğimizi düşünelim mi? Muhtemelen en kolay yol, messageList öğesinin içinde bir dizi düzenlemek olacaktır! Bunu yapalım:

// sunucuya gönderilecek bir nesne oluşturun $req = new request(); $req->messageList = new MesajListesi(); $msg1 = yeni Mesaj(); $msg1->telefon = "79871234567"; $msg1->text = "Mesaj 1'i test edin"; $msg1->tarih = "2013-07-21T15:00:00.26"; $msg1->tür = 15; $msg2 = yeni Mesaj(); $msg2->telefon = "79871234567"; $msg2->text = "Mesaj 2'yi test edin"; $msg2->tarih = "2014-08-22T16:01:10"; $msg2->tür = 16; $msg3 = yeni Mesaj(); $msg3->telefon = "79871234567"; $msg3->text = "Mesaj 3'ü test edin"; $msg3->tarih = "2014-08-22T16:01:10"; $msg3->tür = 17; $req->messageList->mesaj = $msg1; $req->messageList->mesaj = $msg2; $req->messageList->mesaj = $msg3;

Günlüklerimiz istemciden aşağıdaki paketin alındığını gösteriyor:

79871234567 Test mesajı 1 2013-07-21T15:00:00.26 15 79871234567 Test mesajı 2 2014-08-22T16:01:10 16 79871234567 Test mesajı 3 2014-08-22T16:01:10 17

Ne saçmalık dedin? Ve bir bakıma haklı olacaksın, çünkü... Bir nesnenin istemciden çıktığını öğrendiğimizde, sunucumuza tamamen aynı biçimde, bir zarf şeklinde geldi. Doğru, SMS mesajları XML'de ihtiyacımız olan şekilde serileştirilmedi - öğelere sarılmaları gerekiyordu İleti, değil Yapı. Şimdi böyle bir nesnenin yönteme hangi biçimde geldiğini görelim. SMS gönder:

Object(stdClass) public "messageList" => object(stdClass) public "mesaj" => object(stdClass) public "Struct" => dizi (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (uzunluk=11) public "text" => string "Test mesajı 1" (uzunluk=37) public "tarih" => string "2013-07-21T15:00:00.26" (uzunluk=22) public " type" => string "15" (uzunluk=2) 1 => object(stdClass) public "phone" => string "79871234567" (uzunluk=11) public "text" => string "Test mesajı 2" (uzunluk= 37) public "date" => string "2014-08-22T16:01:10" (uzunluk=19) public "type" => string "16" (uzunluk=2) 2 => object(stdClass) public "phone " => string "79871234567" (uzunluk=11) public "text" => string "Test mesajı 3" (uzunluk=37) public "tarih" => string "2014-08-22T16:01:10" (uzunluk= 19) public "type" => string "17" (uzunluk=2)

Bu bilgi bize ne veriyor? Sadece seçtiğimiz yol doğru değil ve “Sunucuda doğru veri yapısını nasıl elde edebiliriz?” sorusuna cevap alamadık. Ancak umutsuzluğa kapılmamanızı ve dizimizi türe dönüştürmeyi denemenizi öneririm. bir obje:

$req->messageList->message = (object)$req->messageList->message;

Bu durumda başka bir zarf alacağız:

79871234567 Test mesajı 1 2013-07-21T15:00:00.26 15 79871234567 Test mesajı 2 2014-08-22T16:01:10 16 79871234567 Test mesajı 3 2014-08-22T16:01:10 17

Yöntemin içine girdi SMS gönder nesne aşağıdaki yapıya sahiptir:

Object(stdClass) public "messageList" => object(stdClass) public "mesaj" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (uzunluk=11) public "text" => string "Test mesajı 1" (uzunluk=37) public "tarih" => string "2013-07-21T15:00:00.26" (uzunluk=22) public " type" => string "15" (uzunluk=2) 1 => object(stdClass) public "phone" => string "79871234567" (uzunluk=11) public "text" => string "Test mesajı 2" (uzunluk= 37) public "date" => string "2014-08-22T16:01:10" (uzunluk=19) public "type" => string "16" (uzunluk=2) 2 => object(stdClass) public "phone " => string "79871234567" (uzunluk=11) public "text" => string "Test mesajı 3" (uzunluk=37) public "tarih" => string "2014-08-22T16:01:10" (uzunluk= 19) public "type" => string "17" (uzunluk=2)

Bana göre “terimlerin yerleri değiştirildiğinde toplam değişmez” (c). Ne SAHTE, Ne Yapı– Henüz hedefimize ulaşamadık! Ve bunu başarmak için, bu anlaşılmaz isimlerin yerine yerli ismimizin görüntülendiğinden emin olmalıyız. İleti. Ancak yazar bunu nasıl başaracağını henüz bilmiyor. Bu nedenle yapabileceğimiz tek şey fazla kaptan kurtulmak. Başka bir deyişle, artık bunun yerine şundan emin olacağız: İleti oldu SAHTE! Bunu yapmak için nesneyi aşağıdaki gibi değiştirin:

// sunucuya gönderilecek bir nesne oluşturun $req = new request(); $msg1 = yeni Mesaj(); $msg1->telefon = "79871234567"; $msg1->text = "Mesaj 1'i test edin"; $msg1->tarih = "2013-07-21T15:00:00.26"; $msg1->tür = 15; $msg2 = yeni Mesaj(); $msg2->telefon = "79871234567"; $msg2->text = "Mesaj 2'yi test edin"; $msg2->tarih = "2014-08-22T16:01:10"; $msg2->tür = 16; $msg3 = yeni Mesaj(); $msg3->telefon = "79871234567"; $msg3->text = "Mesaj 3'ü test edin"; $msg3->tarih = "2014-08-22T16:01:10"; $msg3->tür = 17; $req->messageList = $msg1; $req->messageList = $msg2; $req->messageList = $msg3; $req->messageList = (object)$req->messageList;

Ya şansımız yaver giderse ve şemadan doğru isim çıkarsa? Bunu yapmak için gelen zarfa bakalım:

79871234567 Test mesajı 1 2013-07-21T15:00:00.26 15 79871234567 Test mesajı 2 2014-08-22T16:01:10 16 79871234567 Test mesajı 3 2014-08-22T16:01:10 17

Evet bir mucize gerçekleşmedi! SAHTE– kazanamayacağız! E geldi SMS gönder bu durumda nesne şöyle görünecek:

Object(stdClass) public "messageList" => object(stdClass) public "BOGUS" => dizi (boyut=3) 0 => object(stdClass) public "phone" => string "79871234567" (uzunluk=11) public " text" => string "Test mesajı 1" (uzunluk=37) public "tarih" => string "2013-07-21T15:00:00.26" (uzunluk=22) public "type" => string "15" (uzunluk) =2) 1 => object(stdClass) public "phone" => string "79871234567" (uzunluk=11) public "text" => string "Test mesajı 2" (uzunluk=37) public "tarih" => string " 2014-08-22T16:01:10" (uzunluk=19) public "type" => string "16" (uzunluk=2) 2 => object(stdClass) public "phone" => string "79871234567" (uzunluk= 11) public "text" => string "Test mesajı 3" (uzunluk=37) public "tarih" => string "2014-08-22T16:01:10" (uzunluk=19) public "type" => string " 17" (uzunluk=2)

Dedikleri gibi – “Neredeyse”! Bu (biraz üzücü) not üzerine, yavaş yavaş işleri toparlamayı ve kendimiz için bazı sonuçlar çıkarmayı öneriyorum.

8 Sonuç

Sonunda buraya geldik! Şimdi ne yapabileceğinizi bulalım:

  • web hizmetiniz için gerekli WSDL dosyasını yazabilirsiniz;
  • sunucu ile SOAP aracılığıyla iletişim kurabilen kendi istemcinizi kolayca yazabilirsiniz;
  • SOAP aracılığıyla dış dünyayla iletişim kuran kendi sunucunuzu yazabilirsiniz;
  • istemcinizden sunucuya aynı türdeki nesnelerin dizilerini gönderebilirsiniz (bazı kısıtlamalarla).

Küçük araştırmamız sırasında bazı keşifler de yaptık:

  • yerel SoapClient sınıfı, XML'de aynı türdeki veri yapılarını doğru şekilde serileştirmez;
  • bir diziyi XML'e serileştirirken, adı verilen ekstra bir öğe oluşturur. Yapı;
  • bir nesneyi XML'e serileştirirken, adı verilen ekstra bir öğe oluşturur. SAHTE;
  • SAHTE olduğundan daha az kötü Yapı zarfın daha kompakt olması nedeniyle (zarfın XML başlığına fazladan ad alanı eklenmez);
  • Ne yazık ki SoapServer sınıfı, zarf verilerini XML şemamızla otomatik olarak doğrulamaz (belki diğer sunucular da bunu yapmaz).

Görüntüleme