Dịch vụ Web SOAP sử dụng Spring-WS. Mô tả Dịch vụ Web bằng ngôn ngữ WSDL

mũ Ngày 23 tháng 7 năm 2013 lúc 01:09 chiều

Viết ứng dụng máy khách-máy chủ SOAP bằng PHP

  • PHP
  • Hướng dẫn

Chào mọi người!
Chuyện xảy ra là gần đây tôi bắt đầu phát triển các dịch vụ web. Nhưng hôm nay chủ đề không phải về tôi mà về cách chúng ta có thể viết Dịch vụ Web XML của riêng mình dựa trên giao thức SOAP 1.2.

Tôi hy vọng rằng sau khi đọc chủ đề, bạn sẽ có thể:

  • viết triển khai ứng dụng web trên máy chủ của riêng bạn;
  • viết ứng dụng khách của riêng bạn cho một ứng dụng web;
  • viết mô tả dịch vụ web của riêng bạn (WSDL);
  • gửi các mảng máy khách có cùng loại dữ liệu đến máy chủ.
Như bạn có thể đoán, tất cả điều kỳ diệu sẽ được thực hiện bằng cách sử dụng PHP và các lớp SoapClient và SoapServer tích hợp sẵn. Con thỏ của chúng tôi sẽ là một dịch vụ gửi tin nhắn SMS.

1 Tuyên bố vấn đề

1.1 Ranh giới

Lúc đầu, tôi đề xuất giải quyết kết quả mà chúng ta sẽ đạt được khi kết thúc chủ đề. Như đã thông báo ở trên, chúng tôi sẽ viết một dịch vụ gửi tin nhắn SMS và chính xác hơn là chúng tôi sẽ nhận tin nhắn từ nhiều nguồn khác nhau thông qua giao thức SOAP. Sau đó, chúng tôi sẽ xem xét chúng đến máy chủ dưới hình thức nào. Thật không may, quá trình xếp hàng tin nhắn để gửi tiếp cho nhà cung cấp, thật không may, nằm ngoài phạm vi của bài đăng này vì nhiều lý do.

1.2 Chúng tôi sẽ thay đổi dữ liệu gì?

Tuyệt vời, chúng ta đã quyết định được ranh giới! Bước tiếp theo cần thực hiện là quyết định dữ liệu nào chúng ta sẽ trao đổi giữa máy chủ và máy khách. Về chủ đề này, tôi khuyên bạn không nên chia tóc quá lâu và hãy trả lời ngay những câu hỏi chính cho bản thân:
  • Dữ liệu tối thiểu nào phải được gửi đến máy chủ để gửi tin nhắn SMS đến thuê bao?
  • Dữ liệu tối thiểu nào phải được gửi từ máy chủ để đáp ứng nhu cầu của khách hàng?
Có điều gì đó mách bảo tôi rằng để làm được điều này bạn cần gửi những thông tin sau:
  • số điện thoại di động và
  • văn bản của tin nhắn SMS.
Về nguyên tắc, hai đặc điểm này là đủ để gửi, nhưng tôi tưởng tượng ngay trường hợp một tin nhắn SMS có lời chúc mừng sinh nhật đến với bạn lúc 3 giờ sáng hoặc 4 giờ sáng! Lúc này, tôi sẽ rất biết ơn mọi người vì đã không quên tôi! Vì vậy, chúng tôi cũng sẽ gửi đến máy chủ và
  • ngày gửi tin nhắn SMS.
Điều tiếp theo tôi muốn gửi đến máy chủ là:
  • Loại tin nhắn.
Thông số này không bắt buộc, nhưng nó có thể rất hữu ích cho chúng ta nếu chúng ta cần nhanh chóng nói cho sếp biết có bao nhiêu khách hàng mà chúng ta đã “vui mừng” với tin tức của mình, đồng thời rút ra một số thống kê hay về vấn đề này.

Tuy nhiên, tôi đã quên một cái gì đó! Nếu chúng ta phản ánh nhiều hơn một chút, điều đáng chú ý là khách hàng có thể gửi một hoặc một số tin nhắn SMS đến máy chủ cùng một lúc. Nói cách khác, một gói dữ liệu có thể chứa từ một đến vô số tin nhắn.

Do đó, chúng tôi nhận được rằng để gửi tin nhắn SMS, chúng tôi cần có dữ liệu sau:

  • Số điện thoại,
  • văn bản tin nhắn SMS,
  • thời điểm gửi tin nhắn SMS tới thuê bao,
  • loại tin nhắn.

Chúng ta đã trả lời câu hỏi đầu tiên, bây giờ chúng ta cần trả lời câu hỏi thứ hai. Và có lẽ tôi sẽ cho phép mình quậy phá một chút. Do đó, từ máy chủ, chúng tôi sẽ chỉ gửi dữ liệu Boolean, ý nghĩa của nó có ý nghĩa như sau:

  • TRUE – gói đã đến máy chủ thành công, vượt qua xác thực và xếp hàng để gửi đến nhà cung cấp SMS
  • SAI – trong tất cả các trường hợp khác

Điều này kết thúc phần mô tả của báo cáo vấn đề! Và cuối cùng, hãy chuyển sang phần thú vị - hãy cùng tìm hiểu xem SOAP này là loại quái vật kỳ lạ nào!

2 SOAP là gì?

Nói chung, ban đầu tôi không có ý định viết bất cứ điều gì về SOAP và muốn giới hạn bản thân trong các liên kết đến trang web w3.org với các thông số kỹ thuật cần thiết, cũng như các liên kết đến Wikipedia. Nhưng cuối cùng tôi quyết định viết một đoạn ngắn về giao thức này.

Và tôi sẽ bắt đầu câu chuyện của mình với thực tế là giao thức trao đổi dữ liệu này thuộc một tập hợp con các giao thức dựa trên mô hình được gọi là RPC (Cuộc gọi thủ tục từ xa), phản mã của nó là REST (Chuyển trạng thái đại diện). Bạn có thể đọc thêm về điều này trên Wikipedia; liên kết đến các bài viết nằm ở cuối chủ đề. Từ những bài viết này, chúng ta cần hiểu những điều sau: “Phương pháp RPC cho phép sử dụng một số lượng nhỏ tài nguyên mạng với số lượng lớn phương thức và giao thức phức tạp. Với cách tiếp cận REST, số lượng phương thức và độ phức tạp của giao thức bị hạn chế nghiêm ngặt, điều đó có nghĩa là số lượng tài nguyên riêng lẻ có thể lớn.” Nghĩa là, đối với chúng tôi, điều này có nghĩa là trong trường hợp sử dụng phương pháp RPC trên trang web sẽ luôn có một đầu vào (liên kết) đến dịch vụ và quy trình nào cần gọi để xử lý dữ liệu đến mà chúng tôi chuyển cùng với dữ liệu, trong khi với cách tiếp cận REST trong Trang web của chúng tôi có nhiều đầu vào (liên kết), mỗi đầu vào chỉ chấp nhận và xử lý một số dữ liệu nhất định. Nếu ai đọc biết cách giải thích sự khác biệt trong các cách tiếp cận này một cách đơn giản hơn nữa, hãy nhớ viết bình luận!

Điều tiếp theo chúng ta cần biết về SOAP là giao thức này sử dụng cùng một XML như một phương tiện truyền tải, một mặt điều này rất tốt, bởi vì Kho vũ khí của chúng tôi ngay lập tức bao gồm toàn bộ sức mạnh của một loạt công nghệ dựa trên ngôn ngữ đánh dấu này, cụ thể là Lược đồ XML - ngôn ngữ mô tả cấu trúc của tài liệu XML (cảm ơn Wikipedia!), cho phép xác thực tự động dữ liệu mà máy chủ nhận được từ khách hàng.

Và vì vậy, bây giờ chúng ta biết rằng SOAP là một giao thức được sử dụng để thực hiện các cuộc gọi thủ tục từ xa và nó sử dụng XML làm phương tiện truyền tải! Nếu bạn đọc bài viết trên Wikipedia, bạn cũng có thể biết từ đó rằng nó có thể được sử dụng trên bất kỳ giao thức cấp ứng dụng nào chứ không chỉ kết hợp với HTTP (rất tiếc, trong chủ đề này, chúng ta sẽ chỉ xem xét SOAP qua HTTP). Và bạn biết điều tôi thích nhất ở tất cả những điều này là gì không? Nếu không có phỏng đoán thì tôi sẽ đưa ra gợi ý - SOAP!... Vẫn không đoán được?... Bạn có chắc là mình đã đọc bài viết trên Wikipedia không?... Nói chung là tôi sẽ không tra tấn bạn thêm nữa. Vì vậy, tôi sẽ đi thẳng vào câu trả lời: “SOAP (từ Giao thức truy cập đối tượng đơn giản bằng tiếng Anh - đơn giản giao thức truy cập vào các đối tượng; đạt thông số kỹ thuật 1.2)". Điều đáng chú ý nhất ở dòng này là chữ in nghiêng! Tôi không biết bạn đã rút ra kết luận gì từ tất cả những điều này, nhưng tôi thấy những điều sau - vì giao thức này không thể được gọi là "đơn giản" (và dường như ngay cả w3 cũng đồng ý với điều này), nên từ phiên bản 1.2, bằng cách nào đó, nó đã ngừng được giải mã ! Và nó được gọi là SOAP, chỉ là SOAP thôi.

Được rồi, xin thứ lỗi cho tôi, tôi hơi lạc đề một chút. Như tôi đã viết trước đó, XML được sử dụng làm phương tiện vận chuyển và các gói di chuyển giữa máy khách và máy chủ được gọi là phong bì SOAP. Nếu bạn xem xét cấu trúc chung của chiếc phong bì, bạn sẽ thấy nó rất quen thuộc, bởi vì... giống với cấu trúc của một trang HTML. Nó có một phần chính - phong bì, bao gồm các phần tiêu đềThân hình, hoặc Lỗi. TRONG Thân hình dữ liệu được truyền đi và nó là một phần bắt buộc của phong bì, trong khi tiêu đề Là tùy chọn. TRONG tiêu đềủy quyền hoặc bất kỳ dữ liệu nào khác không liên quan trực tiếp đến dữ liệu đầu vào của quy trình dịch vụ web có thể được truyền đi. Về Lỗi không có gì đặc biệt để nói, ngoại trừ việc nó sẽ đến máy khách từ máy chủ trong trường hợp có bất kỳ lỗi nào.

Đây là lúc câu chuyện đánh giá của tôi về giao thức SOAP kết thúc (chúng ta sẽ xem xét các đường bao và cấu trúc của chúng chi tiết hơn khi máy khách và máy chủ của chúng ta cuối cùng cũng học cách chạy chúng với nhau) và một câu chuyện mới bắt đầu - về người bạn đồng hành SOAP có tên là WSDL(Ngôn ngữ mô tả dịch vụ web). Vâng, vâng, đây chính là điều khiến hầu hết chúng ta sợ hãi thậm chí không dám cố gắng triển khai API của mình trên giao thức này. Do đó, chúng tôi thường phát minh lại bánh xe của mình bằng JSON dưới dạng phương tiện vận chuyển. Vậy WSDL là gì? WSDL là ngôn ngữ để mô tả các dịch vụ web và truy cập chúng, dựa trên ngôn ngữ XML (c) Wikipedia. Nếu định nghĩa này không làm cho bạn hiểu rõ toàn bộ ý nghĩa thiêng liêng của công nghệ này, thì tôi sẽ cố gắng mô tả nó bằng lời của mình!

WSDL được thiết kế để cho phép khách hàng của chúng tôi giao tiếp bình thường với máy chủ. Để thực hiện việc này, tệp có phần mở rộng “*.wsdl” mô tả thông tin sau:

  • Những không gian tên nào đã được sử dụng?
  • Những lược đồ dữ liệu nào đã được sử dụng?
  • Dịch vụ web mong đợi những loại tin nhắn nào từ khách hàng?
  • Dữ liệu nào thuộc về quy trình dịch vụ web nào,
  • Dịch vụ web bao gồm những thủ tục gì?
  • Khách hàng nên gọi các thủ tục dịch vụ web như thế nào,
  • Cuộc gọi của khách hàng nên được gửi đến địa chỉ nào?
Như bạn có thể thấy, tập tin này là toàn bộ dịch vụ web. Bằng cách chỉ định địa chỉ của tệp WSDL trong máy khách, chúng ta sẽ biết mọi thứ về bất kỳ dịch vụ web nào! Do đó, chúng tôi hoàn toàn không cần biết gì về vị trí của dịch vụ web. Tất cả những gì bạn cần biết là vị trí của tệp WSDL của nó! Chúng ta sẽ sớm phát hiện ra rằng SOAP không đáng sợ như những câu tục ngữ Nga vẫn nói.

3 Giới thiệu về Lược đồ XML

Bây giờ chúng ta đã biết rất nhiều về SOAP là gì, bên trong nó có những gì và có cái nhìn tổng quan về hệ thống công nghệ bao quanh nó. Vì, trước hết, SOAP là một phương thức tương tác giữa máy khách và máy chủ và ngôn ngữ đánh dấu XML được sử dụng làm phương tiện vận chuyển cho nó, nên trong phần này chúng ta sẽ hiểu một chút về cách xác thực dữ liệu tự động xảy ra bằng cách sử dụng các lược đồ XML.

Nhiệm vụ chính của sơ đồ là mô tả cấu trúc dữ liệu mà chúng ta sẽ xử lý. Tất cả dữ liệu trong lược đồ XML được chia thành đơn giản(vô hướng) và tổ hợp(cấu trúc) loại. Các loại đơn giản bao gồm các loại sau:

  • đường kẻ,
  • con số,
  • giá trị boolean,
  • ngày của.
Một cái gì đó rất đơn giản không có phần mở rộng bên trong. Phản cực của chúng là loại phức tạp phức tạp. Ví dụ đơn giản nhất về loại phức tạp xuất hiện trong đầu mọi người là đồ vật. Ví dụ, một cuốn sách. Cuốn sách bao gồm các thuộc tính: tác giả, Tên, giá, số ISBN vân vân. Và những thuộc tính này lần lượt có thể là loại đơn giản hoặc loại phức tạp. Và nhiệm vụ của lược đồ XML là mô tả điều này.

Tôi khuyên bạn không nên đi xa và viết lược đồ XML cho tin nhắn SMS của mình! Dưới đây là mô tả xml của tin nhắn SMS:

71239876543 Kiểm thử tin nhắn 2013-07-20T12:00:00 12
Sơ đồ kiểu phức tạp của chúng ta sẽ trông như thế này:


Mục này có nội dung như sau: Chúng tôi có một biến " tin nhắn" kiểu " Tin nhắn" và có một loại phức tạp gọi là " Tin nhắn", bao gồm một tập hợp các phần tử tuần tự" điện thoại" kiểu sợi dây, « chữ" kiểu sợi dây, « ngày" kiểu ngày giờ, « kiểu" kiểu số thập phân. Những loại này đơn giản và đã được xác định trong mô tả lược đồ. Chúc mừng! Chúng tôi vừa viết Lược đồ XML đầu tiên của mình!

Tôi nghĩ rằng ý nghĩa của các yếu tố " yếu tố" Và " loại phức tạp"Mọi thứ ít nhiều đã trở nên rõ ràng với bạn, vì vậy chúng ta sẽ không tập trung vào chúng nữa và hãy chuyển thẳng sang yếu tố soạn nhạc" sự liên tiếp" Khi chúng ta sử dụng phần tử soạn nhạc " sự liên tiếp“Chúng tôi thông báo với bạn rằng các phần tử có trong đó phải luôn được sắp xếp theo trình tự được chỉ định trong sơ đồ và tất cả chúng đều là bắt buộc. Nhưng đừng tuyệt vọng! Có thêm hai phần tử soạn thảo trong lược đồ XML: " sự lựa chọn" Và " tất cả" Nhà soạn nhạc" sự lựa chọn" thông báo rằng phải có một trong các thành phần được liệt kê trong đó và nhà soạn nhạc " tất cả» – bất kỳ sự kết hợp nào của các yếu tố được liệt kê.

Như bạn nhớ, trong phần đầu tiên của chủ đề, chúng ta đã đồng ý rằng có thể truyền từ một đến vô số tin nhắn SMS trong một gói. Vì vậy, tôi đề xuất tìm hiểu cách khai báo dữ liệu đó trong lược đồ XML. Cấu trúc gói chung có thể trông như thế này:

71239876543 Tin nhắn kiểm tra 1 2013-07-20T12:00:00 12 71239876543 Tin nhắn kiểm tra N 2013-07-20T12:00:00 12
Sơ đồ cho một loại phức tạp như vậy sẽ trông như thế này:


Khối đầu tiên chứa khai báo quen thuộc của kiểu phức “ Tin nhắn" Nếu bạn để ý thì trong mỗi loại đơn giản có trong " Tin nhắn", các thuộc tính làm rõ mới đã được thêm vào" phútXảy ra" Và " maxXảy ra" Như bạn có thể đoán từ cái tên, cái đầu tiên ( phútXảy ra) chỉ ra rằng chuỗi này phải chứa ít nhất một phần tử thuộc loại “ điện thoại», « chữ», « ngày" Và " kiểu", trong khi cái tiếp theo ( maxXảy ra) khai báo với chúng ta rằng có nhiều nhất một phần tử như vậy trong chuỗi của chúng ta. Kết quả là, khi chúng tôi viết các lược đồ của riêng mình cho bất kỳ dữ liệu nào, chúng tôi có nhiều lựa chọn nhất về cách định cấu hình chúng!

Khối thứ hai của sơ đồ khai báo phần tử " danh sách tin nhắn" kiểu " Danh sách tin nhắn" Rõ ràng là " Danh sách tin nhắn" là kiểu phức tạp chứa ít nhất một phần tử " tin nhắn", nhưng số lượng phần tử tối đa như vậy không bị giới hạn!

4 Viết WSDL của bạn

Bạn có nhớ rằng WSDL là dịch vụ web của chúng tôi không? Tôi hy vọng bạn nhớ! Khi chúng tôi viết nó, dịch vụ web nhỏ của chúng tôi sẽ chạy trên đó. Vì vậy, tôi đề nghị không nên lộn xộn.

Nói chung, để mọi thứ hoạt động chính xác với chúng tôi, chúng tôi cần chuyển tệp WSDL có loại MIME chính xác cho máy khách. Để thực hiện việc này, bạn cần định cấu hình máy chủ web của mình cho phù hợp, cụ thể là đặt loại MIME cho các tệp có phần mở rộng “*.wsdl” thành dòng sau:

Ứng dụng/wsdl+xml
Nhưng trong thực tế, tôi thường gửi tiêu đề HTTP qua PHP " văn bản/xml»:

Header("Content-Type: text/xml; charset=utf-8");
và mọi thứ đều hoạt động tốt!

Tôi muốn cảnh báo ngay với bạn rằng dịch vụ web đơn giản của chúng tôi sẽ có phần mô tả khá ấn tượng, vì vậy đừng lo lắng, vì... Hầu hết văn bản là nước bắt buộc và sau khi viết nó một lần, bạn có thể liên tục sao chép nó từ dịch vụ web này sang dịch vụ web khác!

Vì WSDL là XML nên bạn cần viết trực tiếp về vấn đề này ngay từ dòng đầu tiên. Phần tử gốc của tệp phải luôn được gọi là " các định nghĩa»:


Thông thường, WSDL bao gồm 4-5 khối chính. Khối đầu tiên là định nghĩa của một dịch vụ web hay nói cách khác là điểm vào.


Ở đây nói rằng chúng tôi có một dịch vụ tên là - “ Dịch vụ SMS" Về nguyên tắc, tất cả các tên trong tệp WSDL có thể được bạn thay đổi thành bất cứ tên nào bạn muốn, bởi vì họ hoàn toàn không có vai trò gì.

Sau đó, chúng tôi thông báo rằng trong dịch vụ web của chúng tôi " Dịch vụ SMS" có một điểm vào ("cổng") tên là " Cổng dịch vụ SMS" Tại điểm vào này, tất cả các yêu cầu từ máy khách đến máy chủ sẽ được gửi. Và chỉ ra trong phần tử “ Địa chỉ» liên kết đến tệp xử lý sẽ chấp nhận yêu cầu.

Khi chúng tôi đã xác định dịch vụ web và chỉ định điểm vào cho dịch vụ đó, chúng tôi cần liên kết các thủ tục được hỗ trợ với dịch vụ đó:


Để làm điều này, nó liệt kê những hoạt động nào và chúng sẽ được gọi dưới dạng nào. Những thứ kia. về cảng" Cổng dịch vụ SMS" một ràng buộc được xác định dưới tên " Ràng buộc dịch vụ Sms", có loại cuộc gọi " rpc"và HTTP được sử dụng làm giao thức truyền tải. Vì vậy, chúng tôi đã chỉ ra ở đây rằng chúng tôi sẽ thực hiện lệnh gọi RPC qua HTTP. Sau đó chúng tôi mô tả các thủ tục ( hoạt động) được hỗ trợ trong dịch vụ web. Chúng tôi sẽ chỉ hỗ trợ một thủ tục – “ gửi tin nhắn" Thông qua thủ tục này, những tin nhắn tuyệt vời của chúng tôi sẽ được gửi đến máy chủ! Sau khi thủ tục được khai báo, cần phải chỉ ra dữ liệu sẽ được truyền dưới dạng nào. Trong trường hợp này, nó được chỉ ra rằng phong bì SOAP tiêu chuẩn sẽ được sử dụng.

Sau đó, chúng ta cần liên kết thủ tục với các tin nhắn:


Để làm điều này, chúng tôi chỉ định rằng liên kết của chúng tôi thuộc loại " SmsServicePortType" và trong phần tử " loại cổng"Với tên cùng loại, chúng tôi chỉ ra sự ràng buộc của các thủ tục với các tin nhắn. Và như vậy, tin nhắn đến (từ client đến server) sẽ được gọi là “ gửiSmsRequest", và gửi đi (từ máy chủ đến máy khách) " gửiSmsPhản hồi" Giống như tất cả các tên trong WSDL, tên của các tin nhắn đến và đi là tùy ý.

Bây giờ chúng ta cần mô tả chính các thông điệp đó, tức là Đến và đi:


Để làm điều này, chúng tôi thêm các phần tử " tin nhắn"có tên" gửiSmsRequest" Và " gửiSmsPhản hồi" tương ứng. Trong đó, chúng tôi chỉ ra rằng đầu vào phải là một đường bao có cấu trúc tương ứng với kiểu dữ liệu " Lời yêu cầu" Sau đó, một phong bì được trả về từ máy chủ chứa kiểu dữ liệu - “ Phản ứng».

Bây giờ chúng ta chỉ cần làm một chút - thêm mô tả về các loại này vào tệp WSDL của chúng ta! Và bạn nghĩ WSDL mô tả dữ liệu đến và đi như thế nào? Tôi nghĩ rằng bạn đã hiểu mọi thứ từ lâu và tự nhủ rằng hãy sử dụng lược đồ XML! Và bạn sẽ hoàn toàn đúng!


Bạn có thể chúc mừng chúng tôi! WSDL đầu tiên của chúng tôi đã được viết! Và chúng ta đang tiến một bước gần hơn đến việc đạt được mục tiêu của mình.
Tiếp theo, chúng ta sẽ xem xét những gì PHP cung cấp cho chúng ta để phát triển các ứng dụng phân tán của riêng mình.

5 Máy chủ SOAP đầu tiên của chúng tôi

Trước đó tôi đã viết rằng để tạo một máy chủ SOAP trong PHP, chúng ta sẽ sử dụng lớp SoapServer tích hợp sẵn. Để tất cả các hành động tiếp theo diễn ra theo cách tương tự như đối với tôi, bạn sẽ cần phải điều chỉnh PHP của mình một chút. Nói chính xác hơn, bạn cần đảm bảo rằng bạn đã cài đặt tiện ích mở rộng “php-soap”. Tốt nhất bạn nên đọc cách cài đặt nó trên máy chủ web của mình trên trang web PHP chính thức (xem danh sách tài liệu tham khảo).

Sau khi mọi thứ đã được cài đặt và định cấu hình, chúng tôi sẽ cần tạo một tệp trong thư mục gốc của máy chủ lưu trữ của bạn “ smsservice.php» với nội dung sau:

setClass("SoapSmsGateWay"); //Khởi động máy chủ $server->handle();
Tôi hy vọng không cần phải giải thích nội dung phía trên dòng với hàm “ini_set”. Bởi vì ở đó nó xác định tiêu đề HTTP nào chúng tôi sẽ gửi từ máy chủ đến máy khách và môi trường được định cấu hình. Trong dòng có “ini_set”, chúng tôi vô hiệu hóa bộ nhớ đệm của tệp WSDL để những thay đổi của chúng tôi trong tệp đó ngay lập tức có hiệu lực trên máy khách.

Bây giờ chúng ta đến với máy chủ! Như bạn có thể thấy, toàn bộ máy chủ SOAP chỉ mất ba dòng! Ở dòng đầu tiên, chúng ta tạo một phiên bản mới của đối tượng SoapServer và chuyển địa chỉ mô tả WSDL của dịch vụ web tới hàm tạo của nó. Bây giờ chúng tôi biết rằng nó sẽ nằm ở thư mục gốc của máy chủ lưu trữ trong một tệp có tên tự giải thích “ smsservice.wsdl.php" Trong dòng thứ hai, chúng ta báo cho máy chủ SOAP biết lớp nào cần được kéo để xử lý phong bì nhận được từ máy khách và trả lại phong bì kèm theo phản hồi. Như bạn có thể đoán, chính trong lớp này phương thức duy nhất của chúng ta sẽ được mô tả gửi tin nhắn. Trên dòng thứ ba, chúng tôi khởi động máy chủ! Thế là xong, máy chủ của chúng tôi đã sẵn sàng! Tôi xin chúc mừng tất cả chúng ta!

Bây giờ chúng ta cần tạo tệp WSDL. Để làm điều này, bạn có thể chỉ cần sao chép nội dung của nó từ phần trước hoặc có quyền tự do “tạo mẫu” cho nó một chút:

"; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http:// Schemas.xmlsoap.org/wsdl/http/" name="SmsWsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> /"> /smsservice.php" />
Ở giai đoạn này, chúng ta nên hoàn toàn hài lòng với máy chủ kết quả, bởi vì Chúng ta có thể ghi lại các phong bì gửi đến và sau đó bình tĩnh phân tích dữ liệu đến. Để chúng tôi nhận được bất cứ thứ gì trên máy chủ, chúng tôi cần một khách hàng. Vì vậy, hay thực hiện ngay bây giơ!

6 ứng dụng khách SOAP đang được triển khai

Trước hết, chúng ta cần tạo một tệp để viết ứng dụng khách. Như thường lệ, chúng ta sẽ tạo nó trong thư mục gốc của Host và gọi nó là " client.php", và bên trong chúng ta sẽ viết như sau:

messageList = MessageList mới(); $req->messageList->message = Tin nhắn mới(); $req->messageList->message->phone = "79871234567"; $req->messageList->message->text = "Kiểm tra tin nhắn 1"; $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));
Hãy mô tả các đối tượng của chúng tôi. Khi chúng tôi viết WSDL, nó mô tả ba thực thể cho phong bì gửi đến máy chủ: Lời yêu cầu, Danh sách tin nhắnTin nhắn. Theo đó các lớp Lời yêu cầu, Danh sách tin nhắnTin nhắn là sự phản ánh của các thực thể này trong tập lệnh PHP của chúng tôi.

Khi chúng ta đã xác định được các đối tượng, chúng ta cần tạo một đối tượng ( $req), mà chúng tôi sẽ gửi đến máy chủ. Và sau đó là hai dòng yêu quý nhất đối với chúng tôi! Khách hàng SOAP của chúng tôi! Dù bạn có tin hay không, điều này là đủ để máy chủ của chúng tôi bắt đầu nhận tin nhắn từ khách hàng, cũng như để máy chủ của chúng tôi nhận và xử lý chúng thành công! Trong phần đầu tiên, chúng tôi tạo một phiên bản của lớp SoapClient và chuyển địa chỉ vị trí của tệp WSDL cho hàm tạo của nó và trong các tham số, chúng tôi chỉ rõ rằng chúng tôi sẽ làm việc bằng giao thức SOAP phiên bản 1.2. Ở dòng tiếp theo chúng ta gọi phương thức gửi tin nhắn sự vật $khách hàng và hiển thị ngay kết quả trên trình duyệt.
Hãy chạy nó và xem cuối cùng chúng ta có được gì!

Đối tượng sau đây đã được trả về cho tôi từ máy chủ:

Đối tượng (stdClass) "trạng thái" công khai => boolean true
Và điều này thật tuyệt vời, bởi vì... Bây giờ chúng tôi biết chắc chắn rằng máy chủ của chúng tôi đang hoạt động và không chỉ hoạt động mà còn có thể trả về một số giá trị cho khách hàng!

Bây giờ chúng ta hãy xem nhật ký mà chúng tôi lưu giữ một cách thận trọng ở phía máy chủ! Trong phần đầu tiên, chúng ta thấy dữ liệu thô đến máy chủ:

79871234567 Tin nhắn kiểm tra 1 2013-07-21T15:00:00.26 15
Đây là phong bì. Bây giờ bạn biết nó trông như thế nào! Nhưng không chắc là chúng ta sẽ quan tâm đến việc xem xét nó mọi lúc, vì vậy hãy giải tuần tự hóa đối tượng khỏi tệp nhật ký và xem mọi thứ có ổn không:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 1 " (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length=2)
Như bạn có thể thấy, đối tượng đã được giải tuần tự hóa một cách chính xác, điều này tôi muốn chúc mừng tất cả chúng ta! Một cái gì đó thú vị hơn đang chờ chúng ta tiếp theo! Cụ thể, chúng tôi sẽ gửi khách hàng đến máy chủ không chỉ một tin nhắn SMS mà cả một gói (chính xác hơn là ba)!

7 Gửi các đối tượng phức tạp

Hãy nghĩ xem làm thế nào chúng ta có thể chuyển cả đống tin nhắn đến máy chủ trong một gói? Có lẽ cách dễ nhất là sắp xếp một mảng bên trong phần tử messageList! Làm thôi nào:

// tạo một đối tượng để gửi đến máy chủ $req = new request(); $req->messageList = MessageList mới(); $msg1 = Tin nhắn mới(); $msg1->phone = "79871234567"; $msg1->text = "Kiểm tra tin nhắn 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = Tin nhắn mới(); $msg2->phone = "79871234567"; $msg2->text = "Kiểm tra tin nhắn 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = Tin nhắn mới(); $msg3->phone = "79871234567"; $msg3->text = "Kiểm tra tin nhắn 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->type = 17; $req->messageList->message = $msg1; $req->messageList->message = $msg2; $req->messageList->message = $msg3;
Nhật ký của chúng tôi cho thấy gói sau đã được nhận từ máy khách:

79871234567 Tin nhắn kiểm tra 1 2013-07-21T15:00:00.26 15 79871234567 Tin nhắn kiểm tra 2 2014-08-22T16:01:10 16 79871234567 Tin nhắn kiểm tra 3 2014-08-22T16:01:10 17
Bạn nói điều vô nghĩa gì vậy? Và bạn sẽ đúng ở một khía cạnh nào đó, bởi vì... Ngay sau khi chúng tôi biết rằng một đối tượng đã rời khỏi máy khách, nó sẽ đến máy chủ của chúng tôi ở dạng hoàn toàn giống nhau dưới dạng một phong bì. Đúng, tin nhắn SMS không được tuần tự hóa dưới dạng XML theo cách chúng tôi cần - chúng phải được gói trong các phần tử tin nhắn, không có trong Cấu trúc. Bây giờ chúng ta hãy xem một đối tượng như vậy xuất hiện dưới dạng nào gửi tin nhắn:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "Struct" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public " type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 2" (length= 37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone " => chuỗi "79871234567" (length=11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length= 19) "loại" công khai => chuỗi "17" (độ dài = 2)
Kiến thức này mang lại cho chúng ta điều gì? Chỉ có điều đường dẫn chúng tôi đã chọn không chính xác và chúng tôi chưa nhận được câu trả lời cho câu hỏi - “Làm cách nào chúng tôi có thể có được cấu trúc dữ liệu chính xác trên máy chủ?” Nhưng tôi khuyên bạn đừng tuyệt vọng và hãy cố gắng chuyển đổi mảng của chúng ta thành kiểu một đối tượng:

$req->messageList->message = (object)$req->messageList->message;
Trong trường hợp này, chúng ta sẽ nhận được một phong bì khác:

79871234567 Tin nhắn kiểm tra 1 2013-07-21T15:00:00.26 15 79871234567 Tin nhắn kiểm tra 2 2014-08-22T16:01:10 16 79871234567 Tin nhắn kiểm tra 3 2014-08-22T16:01:10 17
Đi vào phương pháp gửi tin nhắnđối tượng có cấu trúc sau:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public " type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 2" (length= 37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone " => chuỗi "79871234567" (length=11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length= 19) "loại" công khai => chuỗi "17" (độ dài = 2)
Đối với tôi, “tổng không thay đổi khi thay đổi vị trí của các số hạng” (c). Cái gì không có thật, Cái gì Cấu trúc– chúng ta vẫn chưa đạt được mục tiêu của mình! Và để đạt được điều đó, chúng ta cần đảm bảo rằng thay vì những cái tên khó hiểu này, tên gốc của chúng ta sẽ được hiển thị tin nhắn. Nhưng tác giả vẫn chưa biết làm thế nào để đạt được điều này. Vì vậy, điều duy nhất chúng ta có thể làm là loại bỏ thùng chứa thừa. Nói cách khác, bây giờ chúng ta sẽ đảm bảo rằng thay vì tin nhắnđã trở thành không có thật! Để thực hiện việc này, hãy thay đổi đối tượng như sau:

// tạo một đối tượng để gửi đến máy chủ $req = new request(); $msg1 = Tin nhắn mới(); $msg1->phone = "79871234567"; $msg1->text = "Kiểm tra tin nhắn 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = Tin nhắn mới(); $msg2->phone = "79871234567"; $msg2->text = "Kiểm tra tin nhắn 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = Tin nhắn mới(); $msg3->phone = "79871234567"; $msg3->text = "Kiểm tra tin nhắn 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->type = 17; $req->messageList = $msg1; $req->messageList = $msg2; $req->messageList = $msg3; $req->messageList = (object)$req->messageList;
Điều gì sẽ xảy ra nếu chúng ta may mắn và tên chính xác xuất hiện trên sơ đồ? Để làm điều này, chúng ta hãy nhìn vào phong bì đã đến:

79871234567 Tin nhắn kiểm tra 1 2013-07-21T15:00:00.26 15 79871234567 Tin nhắn kiểm tra 2 2014-08-22T16:01:10 16 79871234567 Tin nhắn kiểm tra 3 2014-08-22T16:01:10 17
Vâng, điều kỳ diệu đã không xảy ra! không có thật– chúng ta sẽ không thắng! Đã tới gửi tin nhắnđối tượng trong trường hợp này sẽ trông như thế này:

Object(stdClass) public "messageList" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public " text" => string "Kiểm tra tin nhắn 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length =2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 2" (length=37) public "date" => string " 2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone" => string "79871234567" (length= 11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string " 17" (chiều dài=2)
Như họ nói - "Gần như"! Về lưu ý này (hơi buồn), tôi đề xuất nên từ từ kết thúc mọi việc và rút ra một số kết luận cho bản thân.

8 Kết luận

Cuối cùng chúng tôi đã đến đây! Hãy tìm hiểu những gì bạn có thể làm bây giờ:
  • bạn có thể viết tệp WSDL cần thiết cho dịch vụ web của mình;
  • bạn có thể dễ dàng viết ứng dụng khách của riêng mình có thể giao tiếp với máy chủ thông qua SOAP;
  • bạn có thể viết máy chủ của riêng mình để liên lạc với thế giới bên ngoài thông qua SOAP;
  • bạn có thể gửi các mảng cùng loại đối tượng đến máy chủ từ máy khách của mình (với một số hạn chế).
Chúng tôi cũng đã thực hiện một số khám phá trong quá trình nghiên cứu nhỏ của mình:
  • lớp SoapClient gốc không tuần tự hóa chính xác các cấu trúc dữ liệu cùng loại trong XML;
  • khi tuần tự hóa một mảng thành XML, nó tạo ra một phần tử bổ sung gọi là Cấu trúc;
  • khi tuần tự hóa một đối tượng thành XML, nó tạo ra một phần tử bổ sung gọi là không có thật;
  • không có thậtít ác hơn Cấu trúc do thực tế là phong bì nhỏ gọn hơn (các không gian tên bổ sung không được thêm vào tiêu đề XML của phong bì);
  • Thật không may, lớp SoapServer không tự động xác thực dữ liệu đường bao bằng lược đồ XML của chúng tôi (có lẽ các máy chủ khác cũng không làm điều này).

Các phần tử mở rộng ràng buộc được sử dụng để chỉ định một ngữ pháp cụ thể cho các thông báo lỗi đến (3) và gửi đi (4) (5). Thông tin về mức độ hoạt động (2) và mức độ ràng buộc (1) cũng có thể được chỉ định.

Phần tử liên kết hoạt động chứa dữ liệu cho hoạt động có cùng tên của loại cổng liên quan. Tuy nhiên, tên của thao tác nói chung không phải là duy nhất (ví dụ: nạp chồng các phương thức/hàm - sử dụng cùng tên nhưng có các chữ ký khác nhau), do đó có thể không đủ để xác định duy nhất thao tác mục tiêu của loại cổng. Trong những trường hợp như vậy, thao tác đích được giải quyết bằng cách chỉ định bổ sung tên phần tử wsdl:input và wsdl:output thích hợp bằng cách sử dụng thuộc tính name.

Ràng buộc phải chỉ cài đặt một giao thức.

Ràng buộc không nên chứa thông tin địa chỉ.

Hải cảng

Một cổng xác định một điểm cuối duy nhất bằng cách đặt địa chỉ để liên kết.

  1. <wsdl:các định nghĩa .... >
  2. <wsdl:dịch vụ .... > *
  3. <wsdl:Hải cảng name = "nmtoken" ràng buộc = "qname" > *
  4. <-- extensibility element (1) -->
  5. wsdl:Hải cảng>
  6. wsdl:dịch vụ>
  7. wsdl:các định nghĩa>

Thuộc tính name chỉ định một tên duy nhất trong số tất cả các cổng trong tài liệu WSDL. Thuộc tính ràng buộc của loại QName chứa tham chiếu đến ràng buộc (xem).

Phần tử mở rộng (1) được sử dụng để chỉ định địa chỉ.

Hải cảng không nên chỉ định nhiều hơn một địa chỉ.

Hải cảng không nên chứa bất kỳ thông tin ràng buộc nào ngoài địa chỉ.

Dịch vụ

Một dịch vụ kết hợp một tập hợp các cổng liên quan lại với nhau.

  1. <wsdl:các định nghĩa .... >
  2. <wsdl:dịch vụ tên = "nmtoken" > *
  3. <wsdl:Hải cảng .... /> *
  4. wsdl:dịch vụ>
  5. wsdl:các định nghĩa>

Thuộc tính name chỉ định một tên duy nhất trong số tất cả các dịch vụ được xác định trong tài liệu WSDL.

Các cổng trong một dịch vụ được kết nối như sau:

  • Các cổng không giao tiếp với nhau (nghĩa là đầu ra của cổng này không phải là đầu vào của cổng khác).
  • Nếu một dịch vụ có nhiều cổng dùng chung một loại cổng nhưng sử dụng các liên kết khác nhau hoặc có địa chỉ khác nhau thì các cổng đó là các cổng thay thế. Mỗi cổng như vậy thực hiện hành vi tương đương về mặt logic (trong các ràng buộc về định dạng truyền tải và thông báo được áp đặt bởi ràng buộc tương ứng). Điều này cho phép khách hàng chọn một cổng cụ thể để liên lạc dựa trên các tiêu chí khác nhau (hỗ trợ giao thức truyền tải, v.v.).
  • Bằng cách xem xét các cổng, bạn có thể xác định loại cổng nào được dịch vụ hỗ trợ. Dựa trên dữ liệu này, khách hàng có thể xác định khả năng tương tác với một dịch vụ cụ thể. Điều này hữu ích nếu có kết nối giữa các hoạt động từ các loại cổng khác nhau và dịch vụ cần hỗ trợ tất cả các loại cổng cần thiết để thực hiện một tác vụ nhất định.
  1. Đây là bản dịch mở rộng, một phần, miễn phí của tài liệu Ngôn ngữ mô tả dịch vụ web (WSDL) 1.1 ngày 15 tháng 3 năm 2001
  2. Sẽ cực kỳ bất tiện khi vận hành với các thuật ngữ không thể giải thích được viết bằng tiếng Latinh và chúng cũng được dịch rõ ràng. Do đó, tên ban đầu chỉ được đặt khi một thuật ngữ mới được đưa ra và hơn nữa trong văn bản, bản dịch tiếng Nga được sử dụng.

WSDL (Ngôn ngữ mô tả dịch vụ web) phiên bản 1.1 được xuất bản vào ngày 15 tháng 3 năm 2001. WSDL là định dạng dựa trên XML được sử dụng để mô tả các dịch vụ web bằng cách sử dụng các thông báo chứa thông tin về cách truy cập một dịch vụ web cụ thể. WSDL có thể mở rộng, cho phép bạn mô tả các dịch vụ và thông báo của chúng bất kể định dạng thông báo hoặc giao thức mạng nào được sử dụng để truyền tải, tuy nhiên, WSDL 1.1 thường được sử dụng nhiều nhất cùng với SOAP 1.1, HTTP GET/POST và MIME. Bởi vì WSDLđược phát triển cùng với SOAP và cùng các công ty Microsoft, Ariba và IBM đã tham gia phát triển nó. Nếu chúng ta xem xét tài liệu WSDL bằng trực giác, chúng ta có thể nói rằng nó cho phép trả lời 4 câu hỏi:

1) Bạn đang làm gì thế? Câu trả lời cho câu hỏi này được đưa ra dưới dạng phù hợp cho cả nhận thức của con người và dạng có thể nhận biết được bằng máy. Câu trả lời cho người trong thẻ:<tên/>, <tài liệu/>, dành cho ô tô -<tin nhắn/>, <loại điểm>

2) Bạn nói tiếng gì? (bạn đang sử dụng loại nào?) Trả lời trong thẻ:<các loại/>

3) tôi sẽ liên lạc với bạn bằng cách nào? (máy khách sẽ truy cập dịch vụ web như thế nào?): HTTP hoặc SMTP. Câu trả lời nằm ở<ràng buộc/>

4) tôi có thể tìm thấy bạn ở đâu? (tôi có thể tìm thấy dịch vụ web này ở đâu hoặc URL của nó là gì?). Câu trả lời là:<dịch vụ/>

Kết cấu:

Mỗi tài liệu WSDL có thể được chia thành ba phần logic:

1. xác định kiểu dữ liệu - xác định loại thông điệp được gửi và nhận bởi dịch vụ XML

2. hoạt động trừu tượng - danh sách các hoạt động có thể được thực hiện với tin nhắn

3. liên kết dịch vụ - phương thức gửi tin nhắn

Tài liệu WSDL có thể được tạo bằng tay, nhưng ngôn ngữ được chính thức hóa nghiêm ngặt WSDL cho phép bạn tự động hóa quá trình viết WSDL-các tài liệu. Nhiều công cụ soạn thảo dịch vụ Web chứa các tiện ích tự động tạo WSDL-files mô tả các dịch vụ Web làm sẵn. Ví dụ: Công cụ soạn thảo dịch vụ web Trục Apache chứa một lớp Java2WSDL, tạo WSDL- một tệp thuộc lớp hoặc giao diện Java mô tả một dịch vụ Web. Gói WSTK của IBM, bao gồm Trục, chứa tiện ích java2wsdl, tạo và chạy một đối tượng từ lớp này. Nó hoạt động từ dòng lệnh.

Các thành phần tài liệu WSDL

Hãy mô tả các thẻ WSDL được sử dụng phổ biến nhất:

Nhãn là thẻ gốc của tất cả các tài liệu WSDL. Nó định nghĩa một số không gian tên:

1)Không gian tên mục tiêu là không gian tên của dịch vụ web của chúng tôi

2) xmlns – không gian tên tài liệu WSDL tiêu chuẩn

3)xmlns: SOAP_ENC – không gian tên được sử dụng để mô tả mã hóa SOAP


4) xmlns: impl và intf – không gian tên triển khai và định nghĩa dịch vụ web của chúng tôi

· Tài liệu định nghĩa dịch vụ web

· Tài liệu triển khai dịch vụ web

Để đơn giản, theo quy định, họ sử dụng 1 tệp chứa tất cả thông tin

Yếu tố - cung cấp thông tin về dữ liệu được truyền từ điểm cuối này sang điểm cuối khác.

Để mô tả một cuộc gọi RPC, bạn phải tạo một thông báo đầu vào và một thông báo đầu ra.

Trong phần tử này, bạn có thể chỉ định các tham số phương thức bằng cách sử dụng phần tử

Yếu tố mô tả và xác định các hoạt động hoặc phương thức được hỗ trợ bởi dịch vụ web

Các hoạt động có thể có thông báo đầu vào cũng như thông báo lỗi.

Yếu tố - mô tả cách các hoạt động được chỉ định trong một loại cổng sẽ được truyền qua mạng. Bởi vì phần tử sử dụng một loại cổng, nó phải chỉ định một loại được xác định ở đâu đó trước đó trong tài liệu.

Yếu tố - cho biết nơi tìm thấy dịch vụ web

Yếu tố nhập khẩu . Phần tử dịch vụ rất thường được phân bổ cho tài liệu wsdl của nó vì lý do thực tế.

Để cho phép kết hợp nhiều tài liệu wsdl thành một, phần tử nhập được sử dụng. Nó cho phép bạn gộp một tài liệu wsdl này vào một tài liệu khác.

Yếu tố các loại cho phép bạn chỉ định loại dữ liệu được truyền nếu chúng không chuẩn.

WSDL hỗ trợ 4 chế độ hoạt động:

· Hoạt động một chiều hoặc một chiều. Tin nhắn được gửi đến điểm cuối dịch vụ. Trong trường hợp này, thao tác chỉ được mô tả bằng một thông báo đầu vào.

· Yêu cầu-Phản hồi – chế độ phản hồi yêu cầu. Chế độ hoạt động này là phổ biến nhất. Trong chế độ này, mô tả hoạt động chứa thông báo đầu vào và đầu ra và thông báo lỗi tùy chọn.

· Hoạt động kiểu yêu cầu-phản hồi. Trong chế độ này, điểm cuối là máy khách của điểm cuối khác. Định dạng hoạt động tương tự như chế độ phản hồi yêu cầu, nhưng dữ liệu đầu ra được liệt kê trước dữ liệu đầu vào.

· Thông báo hoạt động. Chế độ này là một phiên bản khác của chế độ truyền một chiều nguyên thủy, trong đó điểm cuối sẽ gửi tin nhắn thay vì nhận nó. Hoạt động chỉ chứa một thông báo đầu ra.

Trang 2 trên 3

Mô tả bằng WSDL

SOAP hoạt động rất tốt nếu mọi thứ đều được biết về dịch vụ Web. Tuy nhiên, đây không phải là luôn luôn như vậy. Phương tiện mô tả giao diện để truy cập dịch vụ Web là ngôn ngữ WSDL (Ngôn ngữ mô tả dịch vụ web). Tiêu chuẩn này được IBM, Microsoft và webMethods cùng phát triển. Mỗi công ty trong số ba công ty này đều có cách tiếp cận riêng để phát triển một tiêu chuẩn mô tả các dịch vụ Web: IBM tạo ra NASSL, Microsoft phát triển SCL, và webMethods phát triển WIDL.

Kết quả của sự hợp tác của họ là phiên bản 1.1 của ngôn ngữ WSDL. Về W3C, cần lưu ý rằng, cũng như với SOAP, tập đoàn W3C dựa trên phiên bản 1.1 đã phát triển WSDL 1.2, hiện là khuyến nghị của W3C. Mô tả WSDL của một dịch vụ Web chứa tất cả thông tin cần thiết để sử dụng dịch vụ đó, bao gồm các phương thức có sẵn và các tham số của chúng. Thông tin này được chứa trong năm yếu tố sau:

  • - giao thức được hỗ trợ.
  • - Tin nhắn dịch vụ web (yêu cầu, phản hồi).
  • Tất cả các phương pháp có sẵn.
  • - URI dịch vụ.
  • - các loại dữ liệu được sử dụng

Tất cả thông tin này được lưu trữ trong phần tử gốc của mô tả WSDL , Danh sách bên dưới hiển thị một ví dụ về WSDL , mô tả về dịch vụ Web.

Mô tả WSDL của dịch vụ Web

Vâng... bạn không thể tìm ra nó nếu không có kính, nhưng đây là một trong những tệp WSDL (!) Đơn giản nhất. Thật không may, một trong những hạn chế của phần mở rộng SOAP cho PHP 5 là, không giống như các triển khai SOAP khác, nó không tự động tạo ra các mô tả WSDL (ít nhất là chưa). Chắc chắn lỗ hổng này sẽ được sửa chữa trong các phiên bản PHP sau này.

Nhân tiện!

Để tự động tạo mô tả WSDL, bạn có thể sử dụng các triển khai thay thế của giao thức SOAP trong PHP:

Tìm kiếm thư mục bằng UDDI

Bây giờ chúng ta đã biết cách lấy thông tin về một dịch vụ Web và cách truy vấn nó, chúng ta cần học cách tìm một dịch vụ như vậy. Vì mục đích này, có một cái gì đó tương tự như các Trang Vàng, cụ thể là các cơ quan đăng ký UBR (Cơ quan đăng ký doanh nghiệp toàn cầu) - các thư mục dịch vụ web.

Có một số cơ quan đăng ký như vậy, bao gồm cả IBM, Microsoft, NTT-Com và SAP. Các cơ quan đăng ký này đồng bộ hóa dữ liệu của chúng, vì vậy bạn có thể sử dụng bất kỳ cơ quan đăng ký nào trong số chúng. Phiên bản hiện tại của tiêu chuẩn UDDI là UDDI 3.0, mặc dù hầu hết các triển khai đều sử dụng phiên bản 2. Các nhà phát triển tiêu chuẩn này bao gồm các công ty khổng lồ như HP, Intel, Microsoft và Sun.

Để tương tác với UBR có hai loại API: API truy vấn và API xuất bản. Giao diện API truy vấn (Yêu cầu) là để yêu cầu dịch vụ trong sổ đăng ký UBR và giao diện API xuất bản cho phép nhà phát triển đăng ký dịch vụ của họ. Có vẻ như chỉ còn là vấn đề thời gian trước khi nội dung của sổ đăng ký trở nên đầy thư rác :)

Nhân tiện!

Có các cơ quan đăng ký thử nghiệm được thiết kế để kiểm tra việc đăng ký dịch vụ trước khi đặt chúng vào cơ quan đăng ký "thực".

Đây là giao diện của một yêu cầu dịch vụ Web:

SortByNameAsc sắp xếpByDateDesc %hướng dẫn%

Trong ví dụ trên, bạn có thể thấy yêu cầu UDDI được gói gọn trong một thông báo SOAP nên trông khá quen thuộc. Phản hồi cho yêu cầu cũng là một tài liệu SOAP, được hiển thị bên dưới:

Chuyến tham quan có hướng dẫn về dịch vụ web Dịch vụ web mẫu dành cho Sách hướng dẫn du lịch Hướng dẫn tham quan Dịch vụ StockQuote

Cài đặt

Việc cài đặt phần mở rộng SOAP cho PHP5 khá dễ dàng. Trên Windows, mô-đun này nằm trong thư mục con ext của thư mục cài đặt PHP. Để sử dụng nó, bạn cần thêm dòng sau vào tệp php.ini: tiện ích mở rộng=php_soap.dllĐể hoạt động, mô-đun này yêu cầu nó phải được đưa vào PHP 5 theo mặc định, ít nhất là trong phiên bản Windows.

  • Hướng dẫn

Chào mọi người!
Chuyện xảy ra là gần đây tôi bắt đầu phát triển các dịch vụ web. Nhưng hôm nay chủ đề không phải về tôi mà về cách chúng ta có thể viết Dịch vụ Web XML của riêng mình dựa trên giao thức SOAP 1.2.

Tôi hy vọng rằng sau khi đọc chủ đề, bạn sẽ có thể:

  • viết triển khai ứng dụng web trên máy chủ của riêng bạn;
  • viết ứng dụng khách của riêng bạn cho một ứng dụng web;
  • viết mô tả dịch vụ web của riêng bạn (WSDL);
  • gửi các mảng máy khách có cùng loại dữ liệu đến máy chủ.
Như bạn có thể đoán, tất cả điều kỳ diệu sẽ được thực hiện bằng cách sử dụng PHP và các lớp SoapClient và SoapServer tích hợp sẵn. Con thỏ của chúng tôi sẽ là một dịch vụ gửi tin nhắn SMS.

1 Tuyên bố vấn đề

1.1 Ranh giới

Lúc đầu, tôi đề xuất giải quyết kết quả mà chúng ta sẽ đạt được khi kết thúc chủ đề. Như đã thông báo ở trên, chúng tôi sẽ viết một dịch vụ gửi tin nhắn SMS và chính xác hơn là chúng tôi sẽ nhận tin nhắn từ nhiều nguồn khác nhau thông qua giao thức SOAP. Sau đó, chúng tôi sẽ xem xét chúng đến máy chủ dưới hình thức nào. Thật không may, quá trình xếp hàng tin nhắn để gửi tiếp cho nhà cung cấp, thật không may, nằm ngoài phạm vi của bài đăng này vì nhiều lý do.

1.2 Chúng tôi sẽ thay đổi dữ liệu gì?

Tuyệt vời, chúng ta đã quyết định được ranh giới! Bước tiếp theo cần thực hiện là quyết định dữ liệu nào chúng ta sẽ trao đổi giữa máy chủ và máy khách. Về chủ đề này, tôi khuyên bạn không nên chia tóc quá lâu và hãy trả lời ngay những câu hỏi chính cho bản thân:
  • Dữ liệu tối thiểu nào phải được gửi đến máy chủ để gửi tin nhắn SMS đến thuê bao?
  • Dữ liệu tối thiểu nào phải được gửi từ máy chủ để đáp ứng nhu cầu của khách hàng?
Có điều gì đó mách bảo tôi rằng để làm được điều này bạn cần gửi những thông tin sau:
  • số điện thoại di động và
  • văn bản của tin nhắn SMS.
Về nguyên tắc, hai đặc điểm này là đủ để gửi, nhưng tôi tưởng tượng ngay trường hợp một tin nhắn SMS có lời chúc mừng sinh nhật đến với bạn lúc 3 giờ sáng hoặc 4 giờ sáng! Lúc này, tôi sẽ rất biết ơn mọi người vì đã không quên tôi! Vì vậy, chúng tôi cũng sẽ gửi đến máy chủ và
  • ngày gửi tin nhắn SMS.
Điều tiếp theo tôi muốn gửi đến máy chủ là:
  • Loại tin nhắn.
Thông số này không bắt buộc, nhưng nó có thể rất hữu ích cho chúng ta nếu chúng ta cần nhanh chóng nói cho sếp biết có bao nhiêu khách hàng mà chúng ta đã “vui mừng” với tin tức của mình, đồng thời rút ra một số thống kê hay về vấn đề này.

Tuy nhiên, tôi đã quên một cái gì đó! Nếu chúng ta phản ánh nhiều hơn một chút, điều đáng chú ý là khách hàng có thể gửi một hoặc một số tin nhắn SMS đến máy chủ cùng một lúc. Nói cách khác, một gói dữ liệu có thể chứa từ một đến vô số tin nhắn.

Do đó, chúng tôi nhận được rằng để gửi tin nhắn SMS, chúng tôi cần có dữ liệu sau:

  • Số điện thoại,
  • văn bản tin nhắn SMS,
  • thời điểm gửi tin nhắn SMS tới thuê bao,
  • loại tin nhắn.

Chúng ta đã trả lời câu hỏi đầu tiên, bây giờ chúng ta cần trả lời câu hỏi thứ hai. Và có lẽ tôi sẽ cho phép mình quậy phá một chút. Do đó, từ máy chủ, chúng tôi sẽ chỉ gửi dữ liệu Boolean, ý nghĩa của nó có ý nghĩa như sau:

  • TRUE – gói đã đến máy chủ thành công, vượt qua xác thực và xếp hàng để gửi đến nhà cung cấp SMS
  • SAI – trong tất cả các trường hợp khác

Điều này kết thúc phần mô tả của báo cáo vấn đề! Và cuối cùng, hãy chuyển sang phần thú vị - hãy cùng tìm hiểu xem SOAP này là loại quái vật kỳ lạ nào!

2 SOAP là gì?

Nói chung, ban đầu tôi không có ý định viết bất cứ điều gì về SOAP và muốn giới hạn bản thân trong các liên kết đến trang web w3.org với các thông số kỹ thuật cần thiết, cũng như các liên kết đến Wikipedia. Nhưng cuối cùng tôi quyết định viết một đoạn ngắn về giao thức này.

Và tôi sẽ bắt đầu câu chuyện của mình với thực tế là giao thức trao đổi dữ liệu này thuộc một tập hợp con các giao thức dựa trên mô hình được gọi là RPC (Cuộc gọi thủ tục từ xa), phản mã của nó là REST (Chuyển trạng thái đại diện). Bạn có thể đọc thêm về điều này trên Wikipedia; liên kết đến các bài viết nằm ở cuối chủ đề. Từ những bài viết này, chúng ta cần hiểu những điều sau: “Phương pháp RPC cho phép sử dụng một số lượng nhỏ tài nguyên mạng với số lượng lớn phương thức và giao thức phức tạp. Với cách tiếp cận REST, số lượng phương thức và độ phức tạp của giao thức bị hạn chế nghiêm ngặt, điều đó có nghĩa là số lượng tài nguyên riêng lẻ có thể lớn.” Nghĩa là, đối với chúng tôi, điều này có nghĩa là trong trường hợp sử dụng phương pháp RPC trên trang web sẽ luôn có một đầu vào (liên kết) đến dịch vụ và quy trình nào cần gọi để xử lý dữ liệu đến mà chúng tôi chuyển cùng với dữ liệu, trong khi với cách tiếp cận REST trong Trang web của chúng tôi có nhiều đầu vào (liên kết), mỗi đầu vào chỉ chấp nhận và xử lý một số dữ liệu nhất định. Nếu ai đọc biết cách giải thích sự khác biệt trong các cách tiếp cận này một cách đơn giản hơn nữa, hãy nhớ viết bình luận!

Điều tiếp theo chúng ta cần biết về SOAP là giao thức này sử dụng cùng một XML như một phương tiện truyền tải, một mặt điều này rất tốt, bởi vì Kho vũ khí của chúng tôi ngay lập tức bao gồm toàn bộ sức mạnh của một loạt công nghệ dựa trên ngôn ngữ đánh dấu này, cụ thể là Lược đồ XML - ngôn ngữ mô tả cấu trúc của tài liệu XML (cảm ơn Wikipedia!), cho phép xác thực tự động dữ liệu mà máy chủ nhận được từ khách hàng.

Và vì vậy, bây giờ chúng ta biết rằng SOAP là một giao thức được sử dụng để thực hiện các cuộc gọi thủ tục từ xa và nó sử dụng XML làm phương tiện truyền tải! Nếu bạn đọc bài viết trên Wikipedia, bạn cũng có thể biết từ đó rằng nó có thể được sử dụng trên bất kỳ giao thức cấp ứng dụng nào chứ không chỉ kết hợp với HTTP (rất tiếc, trong chủ đề này, chúng ta sẽ chỉ xem xét SOAP qua HTTP). Và bạn biết điều tôi thích nhất ở tất cả những điều này là gì không? Nếu không có phỏng đoán thì tôi sẽ đưa ra gợi ý - SOAP!... Vẫn không đoán được?... Bạn có chắc là mình đã đọc bài viết trên Wikipedia không?... Nói chung là tôi sẽ không tra tấn bạn thêm nữa. Vì vậy, tôi sẽ đi thẳng vào câu trả lời: “SOAP (từ Giao thức truy cập đối tượng đơn giản bằng tiếng Anh - đơn giản giao thức truy cập vào các đối tượng; đạt thông số kỹ thuật 1.2)". Điều đáng chú ý nhất ở dòng này là chữ in nghiêng! Tôi không biết bạn đã rút ra kết luận gì từ tất cả những điều này, nhưng tôi thấy những điều sau - vì giao thức này không thể được gọi là "đơn giản" (và dường như ngay cả w3 cũng đồng ý với điều này), nên từ phiên bản 1.2, bằng cách nào đó, nó đã ngừng được giải mã ! Và nó được gọi là SOAP, chỉ là SOAP thôi.

Được rồi, xin thứ lỗi cho tôi, tôi hơi lạc đề một chút. Như tôi đã viết trước đó, XML được sử dụng làm phương tiện vận chuyển và các gói di chuyển giữa máy khách và máy chủ được gọi là phong bì SOAP. Nếu bạn xem xét cấu trúc chung của chiếc phong bì, bạn sẽ thấy nó rất quen thuộc, bởi vì... giống với cấu trúc của một trang HTML. Nó có một phần chính - phong bì, bao gồm các phần tiêu đềThân hình, hoặc Lỗi. TRONG Thân hình dữ liệu được truyền đi và nó là một phần bắt buộc của phong bì, trong khi tiêu đề Là tùy chọn. TRONG tiêu đềủy quyền hoặc bất kỳ dữ liệu nào khác không liên quan trực tiếp đến dữ liệu đầu vào của quy trình dịch vụ web có thể được truyền đi. Về Lỗi không có gì đặc biệt để nói, ngoại trừ việc nó sẽ đến máy khách từ máy chủ trong trường hợp có bất kỳ lỗi nào.

Đây là lúc câu chuyện đánh giá của tôi về giao thức SOAP kết thúc (chúng ta sẽ xem xét các đường bao và cấu trúc của chúng chi tiết hơn khi máy khách và máy chủ của chúng ta cuối cùng cũng học cách chạy chúng với nhau) và một câu chuyện mới bắt đầu - về người bạn đồng hành SOAP có tên là WSDL(Ngôn ngữ mô tả dịch vụ web). Vâng, vâng, đây chính là điều khiến hầu hết chúng ta sợ hãi thậm chí không dám cố gắng triển khai API của mình trên giao thức này. Do đó, chúng tôi thường phát minh lại bánh xe của mình bằng JSON dưới dạng phương tiện vận chuyển. Vậy WSDL là gì? WSDL là ngôn ngữ để mô tả các dịch vụ web và truy cập chúng, dựa trên ngôn ngữ XML (c) Wikipedia. Nếu định nghĩa này không làm cho bạn hiểu rõ toàn bộ ý nghĩa thiêng liêng của công nghệ này, thì tôi sẽ cố gắng mô tả nó bằng lời của mình!

WSDL được thiết kế để cho phép khách hàng của chúng tôi giao tiếp bình thường với máy chủ. Để thực hiện việc này, tệp có phần mở rộng “*.wsdl” mô tả thông tin sau:

  • Những không gian tên nào đã được sử dụng?
  • Những lược đồ dữ liệu nào đã được sử dụng?
  • Dịch vụ web mong đợi những loại tin nhắn nào từ khách hàng?
  • Dữ liệu nào thuộc về quy trình dịch vụ web nào,
  • Dịch vụ web bao gồm những thủ tục gì?
  • Khách hàng nên gọi các thủ tục dịch vụ web như thế nào,
  • Cuộc gọi của khách hàng nên được gửi đến địa chỉ nào?
Như bạn có thể thấy, tập tin này là toàn bộ dịch vụ web. Bằng cách chỉ định địa chỉ của tệp WSDL trong máy khách, chúng ta sẽ biết mọi thứ về bất kỳ dịch vụ web nào! Do đó, chúng tôi hoàn toàn không cần biết gì về vị trí của dịch vụ web. Tất cả những gì bạn cần biết là vị trí của tệp WSDL của nó! Chúng ta sẽ sớm phát hiện ra rằng SOAP không đáng sợ như những câu tục ngữ Nga vẫn nói.

3 Giới thiệu về Lược đồ XML

Bây giờ chúng ta đã biết rất nhiều về SOAP là gì, bên trong nó có những gì và có cái nhìn tổng quan về hệ thống công nghệ bao quanh nó. Vì, trước hết, SOAP là một phương thức tương tác giữa máy khách và máy chủ và ngôn ngữ đánh dấu XML được sử dụng làm phương tiện vận chuyển cho nó, nên trong phần này chúng ta sẽ hiểu một chút về cách xác thực dữ liệu tự động xảy ra bằng cách sử dụng các lược đồ XML.

Nhiệm vụ chính của sơ đồ là mô tả cấu trúc dữ liệu mà chúng ta sẽ xử lý. Tất cả dữ liệu trong lược đồ XML được chia thành đơn giản(vô hướng) và tổ hợp(cấu trúc) loại. Các loại đơn giản bao gồm các loại sau:

  • đường kẻ,
  • con số,
  • giá trị boolean,
  • ngày của.
Một cái gì đó rất đơn giản không có phần mở rộng bên trong. Phản cực của chúng là loại phức tạp phức tạp. Ví dụ đơn giản nhất về loại phức tạp xuất hiện trong đầu mọi người là đồ vật. Ví dụ, một cuốn sách. Cuốn sách bao gồm các thuộc tính: tác giả, Tên, giá, số ISBN vân vân. Và những thuộc tính này lần lượt có thể là loại đơn giản hoặc loại phức tạp. Và nhiệm vụ của lược đồ XML là mô tả điều này.

Tôi khuyên bạn không nên đi xa và viết lược đồ XML cho tin nhắn SMS của mình! Dưới đây là mô tả xml của tin nhắn SMS:

71239876543 Kiểm thử tin nhắn 2013-07-20T12:00:00 12
Sơ đồ kiểu phức tạp của chúng ta sẽ trông như thế này:


Mục này có nội dung như sau: Chúng tôi có một biến " tin nhắn" kiểu " Tin nhắn" và có một loại phức tạp gọi là " Tin nhắn", bao gồm một tập hợp các phần tử tuần tự" điện thoại" kiểu sợi dây, « chữ" kiểu sợi dây, « ngày" kiểu ngày giờ, « kiểu" kiểu số thập phân. Những loại này đơn giản và đã được xác định trong mô tả lược đồ. Chúc mừng! Chúng tôi vừa viết Lược đồ XML đầu tiên của mình!

Tôi nghĩ rằng ý nghĩa của các yếu tố " yếu tố" Và " loại phức tạp"Mọi thứ ít nhiều đã trở nên rõ ràng với bạn, vì vậy chúng ta sẽ không tập trung vào chúng nữa và hãy chuyển thẳng sang yếu tố soạn nhạc" sự liên tiếp" Khi chúng ta sử dụng phần tử soạn nhạc " sự liên tiếp“Chúng tôi thông báo với bạn rằng các phần tử có trong đó phải luôn được sắp xếp theo trình tự được chỉ định trong sơ đồ và tất cả chúng đều là bắt buộc. Nhưng đừng tuyệt vọng! Có thêm hai phần tử soạn thảo trong lược đồ XML: " sự lựa chọn" Và " tất cả" Nhà soạn nhạc" sự lựa chọn" thông báo rằng phải có một trong các thành phần được liệt kê trong đó và nhà soạn nhạc " tất cả» – bất kỳ sự kết hợp nào của các yếu tố được liệt kê.

Như bạn nhớ, trong phần đầu tiên của chủ đề, chúng ta đã đồng ý rằng có thể truyền từ một đến vô số tin nhắn SMS trong một gói. Vì vậy, tôi đề xuất tìm hiểu cách khai báo dữ liệu đó trong lược đồ XML. Cấu trúc gói chung có thể trông như thế này:

71239876543 Tin nhắn kiểm tra 1 2013-07-20T12:00:00 12 71239876543 Tin nhắn kiểm tra N 2013-07-20T12:00:00 12
Sơ đồ cho một loại phức tạp như vậy sẽ trông như thế này:


Khối đầu tiên chứa khai báo quen thuộc của kiểu phức “ Tin nhắn" Nếu bạn để ý thì trong mỗi loại đơn giản có trong " Tin nhắn", các thuộc tính làm rõ mới đã được thêm vào" phútXảy ra" Và " maxXảy ra" Như bạn có thể đoán từ cái tên, cái đầu tiên ( phútXảy ra) chỉ ra rằng chuỗi này phải chứa ít nhất một phần tử thuộc loại “ điện thoại», « chữ», « ngày" Và " kiểu", trong khi cái tiếp theo ( maxXảy ra) khai báo với chúng ta rằng có nhiều nhất một phần tử như vậy trong chuỗi của chúng ta. Kết quả là, khi chúng tôi viết các lược đồ của riêng mình cho bất kỳ dữ liệu nào, chúng tôi có nhiều lựa chọn nhất về cách định cấu hình chúng!

Khối thứ hai của sơ đồ khai báo phần tử " danh sách tin nhắn" kiểu " Danh sách tin nhắn" Rõ ràng là " Danh sách tin nhắn" là kiểu phức tạp chứa ít nhất một phần tử " tin nhắn", nhưng số lượng phần tử tối đa như vậy không bị giới hạn!

4 Viết WSDL của bạn

Bạn có nhớ rằng WSDL là dịch vụ web của chúng tôi không? Tôi hy vọng bạn nhớ! Khi chúng tôi viết nó, dịch vụ web nhỏ của chúng tôi sẽ chạy trên đó. Vì vậy, tôi đề nghị không nên lộn xộn.

Nói chung, để mọi thứ hoạt động chính xác với chúng tôi, chúng tôi cần chuyển tệp WSDL có loại MIME chính xác cho máy khách. Để thực hiện việc này, bạn cần định cấu hình máy chủ web của mình cho phù hợp, cụ thể là đặt loại MIME cho các tệp có phần mở rộng “*.wsdl” thành dòng sau:

Ứng dụng/wsdl+xml
Nhưng trong thực tế, tôi thường gửi tiêu đề HTTP qua PHP " văn bản/xml»:

Header("Content-Type: text/xml; charset=utf-8");
và mọi thứ đều hoạt động tốt!

Tôi muốn cảnh báo ngay với bạn rằng dịch vụ web đơn giản của chúng tôi sẽ có phần mô tả khá ấn tượng, vì vậy đừng lo lắng, vì... Hầu hết văn bản là nước bắt buộc và sau khi viết nó một lần, bạn có thể liên tục sao chép nó từ dịch vụ web này sang dịch vụ web khác!

Vì WSDL là XML nên bạn cần viết trực tiếp về vấn đề này ngay từ dòng đầu tiên. Phần tử gốc của tệp phải luôn được gọi là " các định nghĩa»:


Thông thường, WSDL bao gồm 4-5 khối chính. Khối đầu tiên là định nghĩa của một dịch vụ web hay nói cách khác là điểm vào.


Ở đây nói rằng chúng tôi có một dịch vụ tên là - “ Dịch vụ SMS" Về nguyên tắc, tất cả các tên trong tệp WSDL có thể được bạn thay đổi thành bất cứ tên nào bạn muốn, bởi vì họ hoàn toàn không có vai trò gì.

Sau đó, chúng tôi thông báo rằng trong dịch vụ web của chúng tôi " Dịch vụ SMS" có một điểm vào ("cổng") tên là " Cổng dịch vụ SMS" Tại điểm vào này, tất cả các yêu cầu từ máy khách đến máy chủ sẽ được gửi. Và chỉ ra trong phần tử “ Địa chỉ» liên kết đến tệp xử lý sẽ chấp nhận yêu cầu.

Khi chúng tôi đã xác định dịch vụ web và chỉ định điểm vào cho dịch vụ đó, chúng tôi cần liên kết các thủ tục được hỗ trợ với dịch vụ đó:


Để làm điều này, nó liệt kê những hoạt động nào và chúng sẽ được gọi dưới dạng nào. Những thứ kia. về cảng" Cổng dịch vụ SMS" một ràng buộc được xác định dưới tên " Ràng buộc dịch vụ Sms", có loại cuộc gọi " rpc"và HTTP được sử dụng làm giao thức truyền tải. Vì vậy, chúng tôi đã chỉ ra ở đây rằng chúng tôi sẽ thực hiện lệnh gọi RPC qua HTTP. Sau đó chúng tôi mô tả các thủ tục ( hoạt động) được hỗ trợ trong dịch vụ web. Chúng tôi sẽ chỉ hỗ trợ một thủ tục – “ gửi tin nhắn" Thông qua thủ tục này, những tin nhắn tuyệt vời của chúng tôi sẽ được gửi đến máy chủ! Sau khi thủ tục được khai báo, cần phải chỉ ra dữ liệu sẽ được truyền dưới dạng nào. Trong trường hợp này, nó được chỉ ra rằng phong bì SOAP tiêu chuẩn sẽ được sử dụng.

Sau đó, chúng ta cần liên kết thủ tục với các tin nhắn:


Để làm điều này, chúng tôi chỉ định rằng liên kết của chúng tôi thuộc loại " SmsServicePortType" và trong phần tử " loại cổng"Với tên cùng loại, chúng tôi chỉ ra sự ràng buộc của các thủ tục với các tin nhắn. Và như vậy, tin nhắn đến (từ client đến server) sẽ được gọi là “ gửiSmsRequest", và gửi đi (từ máy chủ đến máy khách) " gửiSmsPhản hồi" Giống như tất cả các tên trong WSDL, tên của các tin nhắn đến và đi là tùy ý.

Bây giờ chúng ta cần mô tả chính các thông điệp đó, tức là Đến và đi:


Để làm điều này, chúng tôi thêm các phần tử " tin nhắn"có tên" gửiSmsRequest" Và " gửiSmsPhản hồi" tương ứng. Trong đó, chúng tôi chỉ ra rằng đầu vào phải là một đường bao có cấu trúc tương ứng với kiểu dữ liệu " Lời yêu cầu" Sau đó, một phong bì được trả về từ máy chủ chứa kiểu dữ liệu - “ Phản ứng».

Bây giờ chúng ta chỉ cần làm một chút - thêm mô tả về các loại này vào tệp WSDL của chúng ta! Và bạn nghĩ WSDL mô tả dữ liệu đến và đi như thế nào? Tôi nghĩ rằng bạn đã hiểu mọi thứ từ lâu và tự nhủ rằng hãy sử dụng lược đồ XML! Và bạn sẽ hoàn toàn đúng!


Bạn có thể chúc mừng chúng tôi! WSDL đầu tiên của chúng tôi đã được viết! Và chúng ta đang tiến một bước gần hơn đến việc đạt được mục tiêu của mình.
Tiếp theo, chúng ta sẽ xem xét những gì PHP cung cấp cho chúng ta để phát triển các ứng dụng phân tán của riêng mình.

5 Máy chủ SOAP đầu tiên của chúng tôi

Trước đó tôi đã viết rằng để tạo một máy chủ SOAP trong PHP, chúng ta sẽ sử dụng lớp SoapServer tích hợp sẵn. Để tất cả các hành động tiếp theo diễn ra theo cách tương tự như đối với tôi, bạn sẽ cần phải điều chỉnh PHP của mình một chút. Nói chính xác hơn, bạn cần đảm bảo rằng bạn đã cài đặt tiện ích mở rộng “php-soap”. Tốt nhất bạn nên đọc cách cài đặt nó trên máy chủ web của mình trên trang web PHP chính thức (xem danh sách tài liệu tham khảo).

Sau khi mọi thứ đã được cài đặt và định cấu hình, chúng tôi sẽ cần tạo một tệp trong thư mục gốc của máy chủ lưu trữ của bạn “ smsservice.php» với nội dung sau:

setClass("SoapSmsGateWay"); //Khởi động máy chủ $server->handle();
Tôi hy vọng không cần phải giải thích nội dung phía trên dòng với hàm “ini_set”. Bởi vì ở đó nó xác định tiêu đề HTTP nào chúng tôi sẽ gửi từ máy chủ đến máy khách và môi trường được định cấu hình. Trong dòng có “ini_set”, chúng tôi vô hiệu hóa bộ nhớ đệm của tệp WSDL để những thay đổi của chúng tôi trong tệp đó ngay lập tức có hiệu lực trên máy khách.

Bây giờ chúng ta đến với máy chủ! Như bạn có thể thấy, toàn bộ máy chủ SOAP chỉ mất ba dòng! Ở dòng đầu tiên, chúng ta tạo một phiên bản mới của đối tượng SoapServer và chuyển địa chỉ mô tả WSDL của dịch vụ web tới hàm tạo của nó. Bây giờ chúng tôi biết rằng nó sẽ nằm ở thư mục gốc của máy chủ lưu trữ trong một tệp có tên tự giải thích “ smsservice.wsdl.php" Trong dòng thứ hai, chúng ta báo cho máy chủ SOAP biết lớp nào cần được kéo để xử lý phong bì nhận được từ máy khách và trả lại phong bì kèm theo phản hồi. Như bạn có thể đoán, chính trong lớp này phương thức duy nhất của chúng ta sẽ được mô tả gửi tin nhắn. Trên dòng thứ ba, chúng tôi khởi động máy chủ! Thế là xong, máy chủ của chúng tôi đã sẵn sàng! Tôi xin chúc mừng tất cả chúng ta!

Bây giờ chúng ta cần tạo tệp WSDL. Để làm điều này, bạn có thể chỉ cần sao chép nội dung của nó từ phần trước hoặc có quyền tự do “tạo mẫu” cho nó một chút:

"; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http:// Schemas.xmlsoap.org/wsdl/http/" name="SmsWsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> /"> /smsservice.php" />
Ở giai đoạn này, chúng ta nên hoàn toàn hài lòng với máy chủ kết quả, bởi vì Chúng ta có thể ghi lại các phong bì gửi đến và sau đó bình tĩnh phân tích dữ liệu đến. Để chúng tôi nhận được bất cứ thứ gì trên máy chủ, chúng tôi cần một khách hàng. Vì vậy, hay thực hiện ngay bây giơ!

6 ứng dụng khách SOAP đang được triển khai

Trước hết, chúng ta cần tạo một tệp để viết ứng dụng khách. Như thường lệ, chúng ta sẽ tạo nó trong thư mục gốc của Host và gọi nó là " client.php", và bên trong chúng ta sẽ viết như sau:

messageList = MessageList mới(); $req->messageList->message = Tin nhắn mới(); $req->messageList->message->phone = "79871234567"; $req->messageList->message->text = "Kiểm tra tin nhắn 1"; $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));
Hãy mô tả các đối tượng của chúng tôi. Khi chúng tôi viết WSDL, nó mô tả ba thực thể cho phong bì gửi đến máy chủ: Lời yêu cầu, Danh sách tin nhắnTin nhắn. Theo đó các lớp Lời yêu cầu, Danh sách tin nhắnTin nhắn là sự phản ánh của các thực thể này trong tập lệnh PHP của chúng tôi.

Khi chúng ta đã xác định được các đối tượng, chúng ta cần tạo một đối tượng ( $req), mà chúng tôi sẽ gửi đến máy chủ. Và sau đó là hai dòng yêu quý nhất đối với chúng tôi! Khách hàng SOAP của chúng tôi! Dù bạn có tin hay không, điều này là đủ để máy chủ của chúng tôi bắt đầu nhận tin nhắn từ khách hàng, cũng như để máy chủ của chúng tôi nhận và xử lý chúng thành công! Trong phần đầu tiên, chúng tôi tạo một phiên bản của lớp SoapClient và chuyển địa chỉ vị trí của tệp WSDL cho hàm tạo của nó và trong các tham số, chúng tôi chỉ rõ rằng chúng tôi sẽ làm việc bằng giao thức SOAP phiên bản 1.2. Ở dòng tiếp theo chúng ta gọi phương thức gửi tin nhắn sự vật $khách hàng và hiển thị ngay kết quả trên trình duyệt.
Hãy chạy nó và xem cuối cùng chúng ta có được gì!

Đối tượng sau đây đã được trả về cho tôi từ máy chủ:

Đối tượng (stdClass) "trạng thái" công khai => boolean true
Và điều này thật tuyệt vời, bởi vì... Bây giờ chúng tôi biết chắc chắn rằng máy chủ của chúng tôi đang hoạt động và không chỉ hoạt động mà còn có thể trả về một số giá trị cho khách hàng!

Bây giờ chúng ta hãy xem nhật ký mà chúng tôi lưu giữ một cách thận trọng ở phía máy chủ! Trong phần đầu tiên, chúng ta thấy dữ liệu thô đến máy chủ:

79871234567 Tin nhắn kiểm tra 1 2013-07-21T15:00:00.26 15
Đây là phong bì. Bây giờ bạn biết nó trông như thế nào! Nhưng không chắc là chúng ta sẽ quan tâm đến việc xem xét nó mọi lúc, vì vậy hãy giải tuần tự hóa đối tượng khỏi tệp nhật ký và xem mọi thứ có ổn không:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 1 " (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length=2)
Như bạn có thể thấy, đối tượng đã được giải tuần tự hóa một cách chính xác, điều này tôi muốn chúc mừng tất cả chúng ta! Một cái gì đó thú vị hơn đang chờ chúng ta tiếp theo! Cụ thể, chúng tôi sẽ gửi khách hàng đến máy chủ không chỉ một tin nhắn SMS mà cả một gói (chính xác hơn là ba)!

7 Gửi các đối tượng phức tạp

Hãy nghĩ xem làm thế nào chúng ta có thể chuyển cả đống tin nhắn đến máy chủ trong một gói? Có lẽ cách dễ nhất là sắp xếp một mảng bên trong phần tử messageList! Làm thôi nào:

// tạo một đối tượng để gửi đến máy chủ $req = new request(); $req->messageList = MessageList mới(); $msg1 = Tin nhắn mới(); $msg1->phone = "79871234567"; $msg1->text = "Kiểm tra tin nhắn 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = Tin nhắn mới(); $msg2->phone = "79871234567"; $msg2->text = "Kiểm tra tin nhắn 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = Tin nhắn mới(); $msg3->phone = "79871234567"; $msg3->text = "Kiểm tra tin nhắn 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->type = 17; $req->messageList->message = $msg1; $req->messageList->message = $msg2; $req->messageList->message = $msg3;
Nhật ký của chúng tôi cho thấy gói sau đã được nhận từ máy khách:

79871234567 Tin nhắn kiểm tra 1 2013-07-21T15:00:00.26 15 79871234567 Tin nhắn kiểm tra 2 2014-08-22T16:01:10 16 79871234567 Tin nhắn kiểm tra 3 2014-08-22T16:01:10 17
Bạn nói điều vô nghĩa gì vậy? Và bạn sẽ đúng ở một khía cạnh nào đó, bởi vì... Ngay sau khi chúng tôi biết rằng một đối tượng đã rời khỏi máy khách, nó sẽ đến máy chủ của chúng tôi ở dạng hoàn toàn giống nhau dưới dạng một phong bì. Đúng, tin nhắn SMS không được tuần tự hóa dưới dạng XML theo cách chúng tôi cần - chúng phải được gói trong các phần tử tin nhắn, không có trong Cấu trúc. Bây giờ chúng ta hãy xem một đối tượng như vậy xuất hiện dưới dạng nào gửi tin nhắn:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "Struct" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public " type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 2" (length= 37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone " => chuỗi "79871234567" (length=11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length= 19) "loại" công khai => chuỗi "17" (độ dài = 2)
Kiến thức này mang lại cho chúng ta điều gì? Chỉ có điều đường dẫn chúng tôi đã chọn không chính xác và chúng tôi chưa nhận được câu trả lời cho câu hỏi - “Làm cách nào chúng tôi có thể có được cấu trúc dữ liệu chính xác trên máy chủ?” Nhưng tôi khuyên bạn đừng tuyệt vọng và hãy cố gắng chuyển đổi mảng của chúng ta thành kiểu một đối tượng:

$req->messageList->message = (object)$req->messageList->message;
Trong trường hợp này, chúng ta sẽ nhận được một phong bì khác:

79871234567 Tin nhắn kiểm tra 1 2013-07-21T15:00:00.26 15 79871234567 Tin nhắn kiểm tra 2 2014-08-22T16:01:10 16 79871234567 Tin nhắn kiểm tra 3 2014-08-22T16:01:10 17
Đi vào phương pháp gửi tin nhắnđối tượng có cấu trúc sau:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public " type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 2" (length= 37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone " => chuỗi "79871234567" (length=11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length= 19) "loại" công khai => chuỗi "17" (độ dài = 2)
Đối với tôi, “tổng không thay đổi khi thay đổi vị trí của các số hạng” (c). Cái gì không có thật, Cái gì Cấu trúc– chúng ta vẫn chưa đạt được mục tiêu của mình! Và để đạt được điều đó, chúng ta cần đảm bảo rằng thay vì những cái tên khó hiểu này, tên gốc của chúng ta sẽ được hiển thị tin nhắn. Nhưng tác giả vẫn chưa biết làm thế nào để đạt được điều này. Vì vậy, điều duy nhất chúng ta có thể làm là loại bỏ thùng chứa thừa. Nói cách khác, bây giờ chúng ta sẽ đảm bảo rằng thay vì tin nhắnđã trở thành không có thật! Để thực hiện việc này, hãy thay đổi đối tượng như sau:

// tạo một đối tượng để gửi đến máy chủ $req = new request(); $msg1 = Tin nhắn mới(); $msg1->phone = "79871234567"; $msg1->text = "Kiểm tra tin nhắn 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = Tin nhắn mới(); $msg2->phone = "79871234567"; $msg2->text = "Kiểm tra tin nhắn 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = Tin nhắn mới(); $msg3->phone = "79871234567"; $msg3->text = "Kiểm tra tin nhắn 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->type = 17; $req->messageList = $msg1; $req->messageList = $msg2; $req->messageList = $msg3; $req->messageList = (object)$req->messageList;
Điều gì sẽ xảy ra nếu chúng ta may mắn và tên chính xác xuất hiện trên sơ đồ? Để làm điều này, chúng ta hãy nhìn vào phong bì đã đến:

79871234567 Tin nhắn kiểm tra 1 2013-07-21T15:00:00.26 15 79871234567 Tin nhắn kiểm tra 2 2014-08-22T16:01:10 16 79871234567 Tin nhắn kiểm tra 3 2014-08-22T16:01:10 17
Vâng, điều kỳ diệu đã không xảy ra! không có thật– chúng ta sẽ không thắng! Đã tới gửi tin nhắnđối tượng trong trường hợp này sẽ trông như thế này:

Object(stdClass) public "messageList" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public " text" => string "Kiểm tra tin nhắn 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length =2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 2" (length=37) public "date" => string " 2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone" => string "79871234567" (length= 11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string " 17" (chiều dài=2)
Như họ nói - "Gần như"! Về lưu ý này (hơi buồn), tôi đề xuất nên từ từ kết thúc mọi việc và rút ra một số kết luận cho bản thân.

8 Kết luận

Cuối cùng chúng tôi đã đến đây! Hãy tìm hiểu những gì bạn có thể làm bây giờ:
  • bạn có thể viết tệp WSDL cần thiết cho dịch vụ web của mình;
  • bạn có thể dễ dàng viết ứng dụng khách của riêng mình có thể giao tiếp với máy chủ thông qua SOAP;
  • bạn có thể viết máy chủ của riêng mình để liên lạc với thế giới bên ngoài thông qua SOAP;
  • bạn có thể gửi các mảng cùng loại đối tượng đến máy chủ từ máy khách của mình (với một số hạn chế).
Chúng tôi cũng đã thực hiện một số khám phá trong quá trình nghiên cứu nhỏ của mình:
  • lớp SoapClient gốc không tuần tự hóa chính xác các cấu trúc dữ liệu cùng loại trong XML;
  • khi tuần tự hóa một mảng thành XML, nó tạo ra một phần tử bổ sung gọi là Cấu trúc;
  • khi tuần tự hóa một đối tượng thành XML, nó tạo ra một phần tử bổ sung gọi là không có thật;
  • không có thậtít ác hơn Cấu trúc do thực tế là phong bì nhỏ gọn hơn (các không gian tên bổ sung không được thêm vào tiêu đề XML của phong bì);
  • Thật không may, lớp SoapServer không tự động xác thực dữ liệu đường bao bằng lược đồ XML của chúng tôi (có lẽ các máy chủ khác cũng không làm điều này).