ما هو الصابون؟ مقدمة إلى مخطط XML

أهلاً بكم!
لقد حدث أنني بدأت مؤخرًا في تطوير خدمات الويب. لكن الموضوع اليوم لا يتعلق بي، بل يتعلق بكيفية كتابة خدمة ويب XML الخاصة بنا بناءً على بروتوكول SOAP 1.2.

أتمنى بعد قراءة الموضوع أن تكون قادرا على:

  • كتابة تنفيذ الخادم الخاص بك لتطبيق ويب؛
  • كتابة تنفيذ العميل الخاص بك لتطبيق ويب؛
  • كتابة وصف خدمة الويب الخاصة بك (WSDL)؛
  • إرسال صفائف العميل من نفس النوع من البيانات إلى الخادم.

كما كنت قد خمنت، سيتم تنفيذ كل السحر باستخدام PHP وفئات SoapClient وSoapServer المضمنة. سيكون أرنبنا بمثابة خدمة لإرسال الرسائل النصية القصيرة.

1 بيان المشكلة

1.1 الحدود

في البداية أقترح التعامل مع النتيجة التي سنحققها في نهاية الموضوع. كما أعلنا أعلاه، سنكتب خدمة إرسال الرسائل النصية القصيرة، وبشكل أكثر دقة، سنستقبل الرسائل من مصادر مختلفة عبر بروتوكول SOAP. وبعد ذلك، سننظر في الشكل الذي يصلون به إلى الخادم. لسوء الحظ، فإن عملية وضع الرسائل في قائمة الانتظار لتسليمها إلى الموفر خارج نطاق هذا المنشور لأسباب عديدة.

1.2 ما هي البيانات التي سنغيرها؟

عظيم، لقد قررنا الحدود! الخطوة التالية التي يجب اتخاذها هي تحديد البيانات التي سنتبادلها بين الخادم والعميل. في هذا الموضوع أقترح عدم تقصف الشعر لفترة طويلة والإجابة فورًا على الأسئلة الرئيسية لنفسك:

  • ما هو الحد الأدنى من البيانات التي يجب إرسالها إلى الخادم لإرسال رسالة SMS إلى المشترك؟
  • ما هو الحد الأدنى من البيانات التي يجب إرسالها من الخادم لتلبية احتياجات العميل؟

يخبرني شيء ما أنه لهذا تحتاج إلى إرسال ما يلي:

  • رقم الهاتف المحمول و
  • نص الرسالة القصيرة.

من حيث المبدأ، هاتان الخاصيتان تكفيان للإرسال، لكنني أتخيل على الفور حالة رسالة نصية قصيرة تحتوي على تحيات عيد ميلاد تصل إليك في الساعة الثالثة صباحًا أو الرابعة صباحًا! في هذه اللحظة سأكون ممتنًا جدًا للجميع لعدم نسياني! ولذلك، فإننا سوف نرسل أيضا إلى الخادم و

  • تاريخ إرسال الرسالة القصيرة.

الشيء التالي الذي أود إرساله إلى الخادم هو:

  • نوع الرسالة.

هذه المعلمة ليست إلزامية، ولكنها يمكن أن تكون مفيدة جدًا بالنسبة لنا إذا أردنا بسرعة إخبار رئيسنا بعدد عملائنا الذين "سعدناهم" بأخبارنا، وكذلك استخلاص بعض الإحصائيات الجميلة حول هذا الموضوع.

ورغم ذلك نسيت شيئًا! إذا فكرنا أكثر قليلاً، تجدر الإشارة إلى أنه يمكن للعميل إرسال رسالة SMS واحدة أو عدد منها إلى الخادم في المرة الواحدة. بمعنى آخر، يمكن لحزمة بيانات واحدة أن تحتوي على عدد من الرسائل إلى ما لا نهاية.

ونتيجة لذلك، حصلنا على أنه لإرسال رسالة نصية قصيرة نحتاج إلى البيانات التالية:

  • رقم الهاتف الجوال،
  • نص رسالة سمز،
  • وقت إرسال الرسالة القصيرة للمشترك،
  • نوع الرسالة.

لقد أجبنا على السؤال الأول، والآن علينا الإجابة على السؤال الثاني. وربما سأسمح لنفسي بالعبث قليلاً. لذلك، سنرسل من الخادم فقط البيانات المنطقية، والتي يكون معناها على النحو التالي:

  • TRUE - وصلت الحزمة بنجاح إلى الخادم، واجتازت المصادقة وتم وضعها في قائمة الانتظار لإرسالها إلى موفر خدمة الرسائل القصيرة
  • خطأ - في جميع الحالات الأخرى

وبهذا ينتهي وصف بيان المشكلة! وأخيرًا، دعنا ننتقل إلى الجزء الممتع - فلنتعرف على نوع الوحش الغريب الذي يمثله هذا الصابون!

2 ما هو الصابون؟

بشكل عام، لم أخطط في البداية لكتابة أي شيء حول ماهية SOAP وأردت أن أقتصر على الروابط إلى موقع الويب w3.org بالمواصفات اللازمة، بالإضافة إلى الروابط إلى ويكيبيديا. ولكن في النهاية قررت أن أكتب ملاحظة قصيرة حول هذا البروتوكول.

وسأبدأ قصتي بحقيقة أن بروتوكول تبادل البيانات هذا ينتمي إلى مجموعة فرعية من البروتوكولات القائمة على ما يسمى بنموذج RPC (استدعاء الإجراء البعيد)، ونقيضه هو REST (نقل الحالة التمثيلية). يمكنك قراءة المزيد عن هذا على ويكيبيديا، روابط المقالات موجودة في نهاية الموضوع. من هذه المقالات، نحتاج إلى فهم ما يلي: “يسمح نهج RPC باستخدام عدد صغير من موارد الشبكة مع عدد كبير من الأساليب والبروتوكول المعقد. مع نهج REST، يكون عدد الأساليب وتعقيد البروتوكول محدودًا للغاية، مما يعني أن عدد الموارد الفردية يمكن أن يكون كبيرًا. وهذا يعني، فيما يتعلق بنا، أن هذا يعني أنه في الموقع في حالة نهج RPC سيكون هناك دائمًا إدخال (رابط) واحد للخدمة وما هو الإجراء الذي يجب الاتصال به لمعالجة البيانات الواردة التي ننقلها مع البيانات، بينما مع نهج REST في موقعنا، يحتوي الموقع على العديد من المدخلات (الروابط)، كل منها يقبل ويعالج بيانات معينة فقط. إذا كان أي شخص يقرأ كيف يشرح الفرق بين هذه الأساليب بشكل أكثر بساطة، فتأكد من كتابته في التعليقات!

والشيء التالي الذي نحتاج إلى معرفته حول SOAP هو أن هذا البروتوكول يستخدم نفس XML كوسيلة نقل، وهو أمر جيد جدًا من ناحية، لأنه تشتمل ترسانتنا على الفور على القوة الكاملة لمجموعة من التقنيات المستندة إلى لغة الترميز هذه، وهي XML-Schema - وهي لغة لوصف بنية مستند XML (شكرًا لـ Wikipedia!)، والتي تسمح بالتحقق التلقائي من صحة البيانات التي يتلقاها الخادم من العملاء.

وهكذا، نحن نعلم الآن أن SOAP هو بروتوكول يستخدم لتنفيذ استدعاءات الإجراءات عن بعد ويستخدم لغة XML كوسيلة نقل! إذا قرأت المقالة على ويكيبيديا، يمكنك أيضًا أن تتعلم من هناك أنه يمكن استخدامه عبر أي بروتوكول على مستوى التطبيق، وليس فقط مع HTTP (لسوء الحظ، في هذا الموضوع سننظر فقط في SOAP عبر HTTP). وأنت تعرف ما يعجبني أكثر في كل هذا؟ إذا لم تكن هناك تخمينات، فسأعطيك تلميحًا - SOAP!... لا توجد تخمينات بعد؟... هل أنت متأكد من أنك قرأت المقال على ويكيبيديا؟... بشكل عام، لن أعذبك أكثر. لذلك، سأذهب مباشرة إلى الإجابة: "SOAP (من بروتوكول الوصول إلى الكائنات البسيطة باللغة الإنجليزية - بسيط بروتوكولالوصول إلى الأشياء؛ ما يصل إلى المواصفات 1.2)". الشيء الأكثر روعة في هذا الخط هو الخط المائل! لا أعرف ما هي الاستنتاجات التي توصلت إليها من كل هذا، لكنني أرى ما يلي - نظرًا لأنه لا يمكن بأي حال من الأحوال تسمية هذا البروتوكول بأنه "بسيط" (ويبدو أنه حتى w3 يوافق على ذلك)، فمن الإصدار 1.2، توقف فك تشفيره بطريقة ما ! وأصبح يُعرف باسم SOAP، فقط SOAP، فترة.

حسنًا، حسنًا، من فضلك معذرة، لقد أخذنا الأمر جانبًا قليلاً. كما كتبت سابقًا، يتم استخدام XML كوسيلة نقل، وتسمى الحزم التي تنتقل بين العميل والخادم بمغلفات SOAP. إذا نظرت إلى الهيكل العام للظرف، فسوف يبدو مألوفًا جدًا لك، لأنه... يشبه ترميز صفحة HTML. يحتوي على قسم رئيسي - ظرف، والذي يتضمن أقسام رأسو جسم، أو عيب. في جسميتم نقل البيانات وهو قسم إلزامي من المظروف، في حين رأسهو اختياري. في رأسقد يتم نقل الترخيص أو أي بيانات أخرى لا ترتبط مباشرة ببيانات الإدخال الخاصة بإجراءات خدمة الويب. عن عيبلا يوجد شيء خاص يمكن إخباره، إلا أنه يأتي إلى العميل من الخادم في حالة وجود أي أخطاء.

هذا هو المكان الذي تنتهي فيه قصة المراجعة الخاصة بي حول بروتوكول SOAP (سننظر إلى المغلفات نفسها وبنيتها بمزيد من التفصيل عندما يتعلم عميلنا وخادمنا أخيرًا تشغيلهما على بعضهما البعض) وتبدأ قصة جديدة - حول رفيق SOAP المسمى WSDL(لغة ​​وصف خدمات الويب). نعم، نعم، هذا هو الشيء الذي يخيف معظمنا حتى من محاولة تنفيذ واجهة برمجة التطبيقات (API) الخاصة بنا على هذا البروتوكول. ونتيجة لذلك، فإننا عادةً ما نعيد اختراع العجلة باستخدام JSON كوسيلة نقل. إذن ما هو WSDL؟ WSDL هي لغة لوصف خدمات الويب والوصول إليها، بناءً على لغة XML (ج) ويكيبيديا. إذا لم يوضح لك هذا التعريف المعنى المقدس الكامل لهذه التكنولوجيا، فسأحاول وصفها بكلماتي الخاصة!

تم تصميم WSDL للسماح لعملائنا بالتواصل بشكل طبيعي مع الخادم. للقيام بذلك، يصف الملف ذو الامتداد "*.wsdl" المعلومات التالية:

  • ما مساحات الأسماء التي تم استخدامها؟
  • ما هي مخططات البيانات التي تم استخدامها؟
  • ما أنواع الرسائل التي تتوقعها خدمة الويب من العملاء؟
  • ما هي البيانات التي تنتمي إلى إجراءات خدمة الويب،
  • ما هي الإجراءات التي تحتوي عليها خدمة الويب؟
  • كيف يجب على العميل الاتصال بإجراءات خدمة الويب،
  • إلى أي عنوان ينبغي إرسال مكالمات العملاء؟

كما ترون، هذا الملف هو خدمة الويب بأكملها. من خلال تحديد عنوان ملف WSDL في العميل، سنعرف كل شيء عن أي خدمة ويب! ونتيجة لذلك، لا نحتاج إلى معرفة أي شيء على الإطلاق عن مكان وجود خدمة الويب نفسها. كل ما تحتاج إلى معرفته هو موقع ملف WSDL الخاص به! سنكتشف قريبًا أن الصابون ليس مخيفًا كما تصوره الأمثال الروسية.

3 مقدمة إلى مخطط XML

الآن نحن نعرف الكثير عن ماهية SOAP، وما بداخلها، ولدينا نظرة عامة على مجموعة التكنولوجيا المحيطة به. نظرًا لأن SOAP، أولاً وقبل كل شيء، هو وسيلة للتفاعل بين العميل والخادم، ويتم استخدام لغة ترميز XML كوسيلة نقل له، فسوف نفهم في هذا القسم قليلاً عن كيفية حدوث التحقق التلقائي من البيانات باستخدام مخططات XML.

تتمثل المهمة الرئيسية للمخطط في وصف بنية البيانات التي سنقوم بمعالجتها. يتم تقسيم كافة البيانات في مخططات XML إلى بسيط(العددية) و معقدأنواع (الهياكل). تشمل الأنواع البسيطة الأنواع التالية:

  • خط،
  • رقم،
  • قيمة منطقية,
  • تاريخ.

شيء بسيط جدًا ليس له امتدادات بالداخل. نقيضهم هو أنواع معقدة معقدة. إن أبسط مثال على النوع المعقد الذي يتبادر إلى ذهن الجميع هو الأشياء. على سبيل المثال، كتاب. يتكون الكتاب من خصائص: مؤلف, اسم, سعر, رقم ISBNإلخ. وهذه الخصائص بدورها يمكن أن تكون إما أنواعًا بسيطة أو أنواعًا معقدة. ومهمة مخطط XML هي وصف ذلك.

أقترح عدم المضي قدمًا وكتابة مخطط XML لرسالتنا النصية القصيرة! فيما يلي وصف XML للرسالة النصية القصيرة:

71239876543 رسالة اختبارية 2013-07-20T12:00:00 12

سيبدو مخططنا المعقد للنوع كما يلي:

يقرأ هذا الإدخال كما يلي: لدينا متغير " رسالة" يكتب " رسالة"وهناك نوع معقد يسمى" رسالة"، والذي يتكون من مجموعة متسلسلة من العناصر" هاتف" يكتب خيط, « نص" يكتب خيط, « تاريخ" يكتب dateTime, « يكتب" يكتب عدد عشري. هذه الأنواع بسيطة وتم تعريفها بالفعل في وصف المخطط. تهانينا! لقد كتبنا للتو مخطط XML الأول الخاص بنا!

أعتقد أن معنى العناصر " عنصر" و " complexType"لقد أصبح كل شيء واضحًا بالنسبة لك، لذا لن نركز عليه بعد الآن ولننتقل مباشرة إلى عنصر الملحن" تسلسل" عندما نستخدم عنصر الملحن " تسلسل"نبلغك أن العناصر المضمنة فيه يجب أن تكون موجودة دائمًا بالتسلسل المحدد في الرسم التخطيطي، وكلها إلزامية. لكن لا تيأس! هناك عنصران إضافيان للمؤلف في مخططات XML: " خيار" و " الجميع" ملحن " خيار" يعلن أنه يجب أن يكون هناك أحد العناصر المدرجة فيه، والملحن " الجميع» – أي مجموعة من العناصر المدرجة.

كما تتذكر، اتفقنا في القسم الأول من الموضوع على أنه يمكن إرسال رسائل SMS من رسالة واحدة إلى ما لا نهاية في حزمة. لذلك، أقترح فهم كيفية الإعلان عن هذه البيانات في مخطط XML. قد يبدو هيكل الحزمة العام كما يلي:

71239876543 رسالة الاختبار 1 2013-07-20T12:00:00 12 71239876543 رسالة الاختبار N 2013-07-20T12:00:00 12

سيبدو الرسم التخطيطي لمثل هذا النوع المعقد كما يلي:

تحتوي الكتلة الأولى على إعلان مألوف من النوع المعقد " رسالة" إذا لاحظت، ففي كل نوع بسيط مدرج في " رسالة"، تمت إضافة سمات توضيحية جديدة" minOccurs" و " maxOccurs" كما قد تخمن من الاسم، الأول ( minOccurs) يشير إلى أن هذا التسلسل يجب أن يحتوي على عنصر واحد على الأقل من النوع " هاتف», « نص», « تاريخ" و " يكتب"، بينما التالي ( maxOccurs) تعلن لنا أن هناك عنصرًا واحدًا على الأقل في تسلسلنا. ونتيجة لذلك، عندما نكتب مخططاتنا الخاصة لأية بيانات، فإننا نمنح أوسع خيار في كيفية تكوينها!

تعلن الكتلة الثانية من الرسم التخطيطي عن العنصر " قائمة الرسائل" يكتب " قائمة الرسائل" انه واضح " قائمة الرسائل" هو نوع معقد يحتوي على عنصر واحد على الأقل " رسالة"، ولكن الحد الأقصى لعدد هذه العناصر غير محدود!

4 اكتب WSDL الخاص بك

هل تتذكر أن WSDL هي خدمة الويب الخاصة بنا؟ آمل أن تتذكر! بينما نكتبها، سيتم تشغيل خدمة الويب الصغيرة الخاصة بنا عليها. لذلك أقترح عدم العبث.

بشكل عام، لكي يعمل كل شيء بشكل صحيح بالنسبة لنا، نحتاج إلى نقل ملف WSDL بنوع MIME الصحيح إلى العميل. للقيام بذلك، تحتاج إلى تكوين خادم الويب الخاص بك وفقًا لذلك، أي تعيين نوع MIME للملفات ذات الامتداد "*.wsdl" على السطر التالي:

التطبيق/وسدل+إكسمل

لكن من الناحية العملية، عادةً ما أقوم بإرسال رأس HTTP عبر PHP " نص/أكس أم أل»:

Header("نوع المحتوى: نص/xml; مجموعة الأحرف=utf-8");

وكل شيء يعمل بشكل رائع!

أريد أن أحذرك على الفور من أن خدمة الويب البسيطة لدينا سيكون لها وصف مثير للإعجاب إلى حد ما، لذلك لا تنزعج، لأن... معظم النص عبارة عن ماء إلزامي، وبعد كتابته مرة واحدة، يمكنك نسخه باستمرار من خدمة ويب إلى أخرى!

نظرًا لأن WSDL هو XML، فأنت بحاجة إلى الكتابة عن هذا مباشرة في السطر الأول. يجب دائمًا تسمية العنصر الجذر للملف بـ " تعريفات»:

عادة، يتكون WSDL من 4-5 كتل رئيسية. الكتلة الأولى هي تعريف خدمة الويب، أو بمعنى آخر، نقطة الدخول.

مكتوب هنا أن لدينا خدمة تسمى - " خدمة الرسائل القصيرة" من حيث المبدأ، يمكنك تغيير جميع الأسماء الموجودة في ملف WSDL إلى ما تريد، لأنه إنهم لا يلعبون أي دور على الإطلاق.

بعد هذا نعلن عن ذلك في خدمة الويب الخاصة بنا " خدمة الرسائل القصيرة"هناك نقطة دخول ("المنفذ") تسمى " منفذ خدمة الرسائل القصيرة" إلى نقطة الدخول هذه سيتم إرسال جميع الطلبات من العملاء إلى الخادم. وتشير في العنصر " عنوان» رابط إلى ملف المعالج الذي سيقبل الطلبات.

بمجرد تعريفنا لخدمة الويب وتحديد نقطة الدخول لها، نحتاج إلى ربط الإجراءات المدعومة بها:

للقيام بذلك، فهو يسرد العمليات وبأي شكل سيتم استدعاؤها. أولئك. للميناء " منفذ خدمة الرسائل القصيرة"يتم تعريف الارتباط تحت الاسم" SMSServiceBinding"، الذي يحتوي على نوع الاتصال" RPC"ويُستخدم HTTP كبروتوكول نقل. وبالتالي، أشرنا هنا إلى أننا سنقوم بإجراء استدعاء RPC عبر HTTP. بعد ذلك نصف الإجراءات ( عملية) مدعومة في خدمة الويب. سندعم إجراءً واحدًا فقط – " أرسل رسالة نصية قصيرة" من خلال هذا الإجراء سيتم إرسال رسائلنا الرائعة إلى الخادم! بعد الإعلان عن الإجراء، من الضروري الإشارة إلى الشكل الذي سيتم إرسال البيانات إليه. في هذه الحالة، يُشار إلى أنه سيتم استخدام مظاريف SOAP القياسية.

بعد ذلك، نحتاج إلى ربط الإجراء بالرسائل:

للقيام بذلك، نحدد أن ربطنا من النوع " SMSServicePortType"وفي العنصر" نوع المنفذ"بالاسم من نفس النوع نشير إلى ربط الإجراءات بالرسائل. وهكذا، سيتم استدعاء الرسالة الواردة (من العميل إلى الخادم) " sendSmsRequest"، والصادرة (من الخادم إلى العميل)" sendSmsResponse" مثل كافة الأسماء في WSDL، تكون أسماء الرسائل الواردة والصادرة عشوائية.

الآن نحن بحاجة إلى وصف الرسائل نفسها، أي. الواردة والصادرة:

للقيام بذلك نضيف العناصر " رسالة"مع الأسماء" sendSmsRequest" و " sendSmsResponse" على التوالى. نشير فيها إلى أن الإدخال يجب أن يكون مظروفًا يتوافق هيكله مع نوع البيانات " طلب" وبعد ذلك يتم إرجاع مظروف من الخادم يحتوي على نوع البيانات - " إجابة».

الآن علينا أن نفعل القليل - أضف وصفًا لهذه الأنواع إلى ملف WSDL الخاص بنا! وكيف تعتقد أن WSDL يصف البيانات الواردة والصادرة؟ أعتقد أنك قد فهمت كل شيء منذ وقت طويل وأخبرت نفسك أنك تستخدم مخططات XML! وسوف تكون على حق تماما!

يمكنك أن تهنئنا! تمت كتابة أول WSDL لدينا! ونحن على بعد خطوة واحدة من تحقيق هدفنا.
بعد ذلك، سنلقي نظرة على ما توفره لنا لغة PHP لتطوير تطبيقاتنا الموزعة.

5 أول خادم SOAP لدينا

كتبت سابقًا أنه لإنشاء خادم SOAP في PHP، سنستخدم فئة SoapServer المضمنة. لكي تتم جميع الإجراءات الإضافية بنفس الطريقة بالنسبة لي، ستحتاج إلى تعديل PHP الخاص بك قليلاً. ولكي نكون أكثر دقة، يجب عليك التأكد من تثبيت ملحق "php-soap". من الأفضل قراءة كيفية تثبيته على خادم الويب الخاص بك على موقع PHP الرسمي (انظر قائمة المراجع).

بعد تثبيت كل شيء وتكوينه، سنحتاج إلى إنشاء ملف في المجلد الجذر لاستضافتك " خدمة الرسائل القصيرة.php» بالمحتوى التالي:

setClass("SoapSmsGateWay"); // ابدأ الخادم $server->handle();

آمل ألا تكون هناك حاجة لشرح ما هو موجود فوق السطر في وظيفة "ini_set". لأن هناك يتم تحديد رؤوس HTTP التي سنرسلها من الخادم إلى العميل ويتم تكوين البيئة. في السطر مع "ini_set"، نقوم بتعطيل التخزين المؤقت لملف WSDL بحيث تصبح التغييرات التي أجريناها سارية المفعول على العميل على الفور.

الآن نأتي إلى الخادم! كما ترون، فإن خادم SOAP بأكمله يستغرق ثلاثة أسطر فقط! في السطر الأول، نقوم بإنشاء مثيل جديد لكائن SoapServer وتمرير عنوان وصف WSDL الخاص بخدمة الويب إلى مُنشئه. الآن نعلم أنه سيكون موجودًا في جذر الاستضافة في ملف يحمل الاسم الذي لا يحتاج إلى شرح " smsservice.wsdl.php" في السطر الثاني، نخبر خادم SOAP بالفئة التي يجب سحبها من أجل معالجة المغلف المستلم من العميل وإرجاع المغلف مع الاستجابة. كما كنت قد خمنت، في هذا الفصل سيتم وصف طريقتنا الوحيدة أرسل رسالة نصية قصيرة. في السطر الثالث نبدأ الخادم! هذا كل شيء، خادمنا جاهز! الذي أهنئنا به جميعًا!

الآن نحن بحاجة إلى إنشاء ملف WSDL. للقيام بذلك، يمكنك إما ببساطة نسخ محتوياته من القسم السابق، أو أخذ الحرية و"تصميمه" قليلًا:

"; ?> /" 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" />

في هذه المرحلة، يجب أن نكون راضين تمامًا عن الخادم الناتج، لأنه يمكننا تسجيل المظاريف القادمة إليه ومن ثم تحليل البيانات الواردة بهدوء. لكي نتمكن من تلقي أي شيء على الخادم، نحتاج إلى عميل. بحيث يتيح الحصول عليه!

6 عميل SOAP في الطريق

أولاً، نحتاج إلى إنشاء ملف نكتب فيه العميل. كالعادة، سنقوم بإنشائه في جذر المضيف ونطلق عليه اسم " client.php"، وفي الداخل سنكتب ما يلي:

messageList = new messageList(); $req->messageList->message = new message(); $req->messageList->message->phone = "79871234567"; $req->messageList->message->text = "رسالة الاختبار 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));

دعونا نصف كائناتنا. عندما كتبنا WSDL، وصفنا ثلاثة كيانات للمغلف الوارد إلى الخادم: طلب, قائمة الرسائلو رسالة. وفقا لذلك الطبقات طلب, قائمة الرسائلو رسالةهي انعكاسات لهذه الكيانات في برنامج PHP النصي الخاص بنا.

بمجرد أن نحدد الكائنات، نحتاج إلى إنشاء كائن ( $req)، والتي سوف نرسلها إلى الخادم. وبعد ذلك يأتي السطران الأكثر عزيزة بالنسبة لنا! عميلنا للصابون! صدق أو لا تصدق، هذا يكفي لخادمنا لبدء تلقي الرسائل من العميل، وكذلك لخادمنا لتلقيها ومعالجتها بنجاح! في أولها، نقوم بإنشاء مثيل لفئة SoapClient ونمرر عنوان موقع ملف WSDL إلى منشئه، وفي المعلمات نشير بوضوح إلى أننا سنعمل باستخدام إصدار بروتوكول SOAP 1.2. في السطر التالي نسمي الطريقة أرسل رسالة نصية قصيرةهدف $clientوعرض النتيجة على الفور في المتصفح.
دعونا تشغيله ونرى ما حصلنا عليه في النهاية!

تم إرجاع الكائن التالي لي من الخادم:

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

وهذا شيء عظيم، لأنه... الآن نحن نعلم يقينًا أن الخادم الخاص بنا يعمل ولا يعمل فقط، بل يمكنه أيضًا إرجاع بعض القيم إلى العميل!

الآن دعونا نلقي نظرة على السجل الذي نحتفظ به بحكمة على جانب الخادم! في جزئه الأول نرى البيانات الأولية التي وصلت إلى الخادم:

79871234567 رسالة الاختبار 1 2013-07-21T15:00:00.26 15

هذا هو المغلف. الآن أنت تعرف كيف يبدو! ولكن من غير المرجح أن نكون مهتمين بالنظر إليه طوال الوقت، لذلك دعونا نقوم بإلغاء تسلسل الكائن من ملف السجل ومعرفة ما إذا كان كل شيء على ما يرام:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "phone" => سلسلة "79871234567" (الطول=11) public "text" => سلسلة "رسالة اختبارية 1 "(الطول = 37) "التاريخ" العام => السلسلة "21T15-07-2013:00:00.26" (الطول = 22) "النوع" العام => السلسلة "15" (الطول = 2)

كما ترون، تم إلغاء تسلسل الكائن بشكل صحيح، وأود أن أهنئنا جميعًا على ذلك! شيء أكثر إثارة للاهتمام ينتظرنا بعد ذلك! على وجه التحديد، سنرسل العميل إلى الخادم ليس فقط رسالة نصية قصيرة واحدة، ولكن حزمة كاملة (على وجه التحديد، ثلاثة)!

7 إرسال الأشياء المعقدة

دعونا نفكر في كيفية نقل مجموعة كاملة من الرسائل إلى الخادم في حزمة واحدة؟ ربما تكون الطريقة الأسهل هي تنظيم مصفوفة داخل عنصر messageList! هيا بنا نقوم بذلك:

// إنشاء كائن لإرساله إلى الخادم $req = new Request(); $req->messageList = new messageList(); $msg1 = رسالة جديدة(); $msg1->phone = "79871234567"; $msg1->text = "رسالة الاختبار 1"; $msg1->date = "21-07-2013T15:00:00.26"; $msg1->type = 15; $msg2 = رسالة جديدة(); $msg2->phone = "79871234567"; $msg2->text = "رسالة الاختبار 2"; $msg2->date = "22-08-2014T16:01:10"; $msg2->type = 16; $msg3 = رسالة جديدة(); $msg3->phone = "79871234567"; $msg3->text = "رسالة الاختبار 3"; $msg3->date = "22-08-2014T16:01:10"; $msg3->type = 17; $req->messageList->message = $msg1; $req->messageList->message = $msg2; $req->messageList->message = $msg3;

تشير سجلاتنا إلى أنه تم استلام الحزمة التالية من العميل:

79871234567 رسالة الاختبار 1 2013-07-21T15:00:00.26 15 79871234567 رسالة الاختبار 2 2014-08-22T16:01:10 16 79871234567 رسالة الاختبار 3 2014-08-22T16:01:10 17

ما هذا الهراء، تقول؟ وسوف تكون على حق إلى حد ما، لأنه... بمجرد أن علمنا أن الكائن قد غادر العميل، فقد وصل إلى خادمنا بنفس الشكل تمامًا في شكل مظروف. صحيح أن رسائل SMS لم يتم تسلسلها بتنسيق XML بالطريقة التي نحتاجها - كان لا بد من تغليفها بالعناصر رسالة، ليس في هيكل. الآن دعونا نرى كيف يأتي هذا الكائن إلى الطريقة أرسل رسالة نصية قصيرة:

كائن (stdClass) عام "messageList" => كائن (stdClass) عام "رسالة" => كائن (stdClass) عام "هيكل" => صفيف (الحجم = 3) 0 => كائن (stdClass) عام "هاتف" => سلسلة "79871234567" (الطول=11) "نص" عام => سلسلة "رسالة اختبارية 1" (الطول=37) "تاريخ" عام => سلسلة "21T15-07-2013"15:00:00.26" (الطول=22) عام " اكتب" => سلسلة "15" (الطول = 2) 1 => كائن (stdClass) عام "هاتف" => سلسلة "79871234567" (الطول = 11) عام "نص" => سلسلة "رسالة اختبار 2" (الطول = 37) "تاريخ" عام => سلسلة "22-08-2014T16:01:10" (الطول = 19) "نوع" عام => سلسلة "16" (الطول = 2) 2 => كائن (stdClass) عام "هاتف " => سلسلة "79871234567" (الطول = 11) سلسلة "نص" عامة => سلسلة "رسالة اختبار 3" (الطول = 37) سلسلة "تاريخ" عامة => سلسلة "22T14-08-2014:01:10" (الطول = 19) "النوع" العام => السلسلة "17" (الطول = 2)

ماذا تعطينا هذه المعرفة؟ فقط أن المسار الذي اخترناه غير صحيح ولم نتلق إجابة على السؤال - "كيف يمكننا الحصول على بنية البيانات الصحيحة على الخادم؟" لكنني أقترح عدم اليأس ومحاولة تحويل مجموعتنا إلى النوع شيء:

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

في هذه الحالة سوف نحصل على مظروف آخر:

79871234567 رسالة الاختبار 1 2013-07-21T15:00:00.26 15 79871234567 رسالة الاختبار 2 2014-08-22T16:01:10 16 79871234567 رسالة الاختبار 3 2014-08-22T16:01:10 17

دخلت في الطريقة أرسل رسالة نصية قصيرةالكائن لديه البنية التالية:

كائن (stdClass) عام "messageList" => كائن (stdClass) عام "رسالة" => كائن (stdClass) عام "BOGUS" => صفيف (الحجم = 3) 0 => كائن (stdClass) عام "هاتف" => سلسلة "79871234567" (الطول=11) "نص" عام => سلسلة "رسالة اختبارية 1" (الطول=37) "تاريخ" عام => سلسلة "21T15-07-2013"15:00:00.26" (الطول=22) عام " اكتب" => سلسلة "15" (الطول = 2) 1 => كائن (stdClass) عام "هاتف" => سلسلة "79871234567" (الطول = 11) عام "نص" => سلسلة "رسالة اختبار 2" (الطول = 37) "تاريخ" عام => سلسلة "22-08-2014T16:01:10" (الطول = 19) "نوع" عام => سلسلة "16" (الطول = 2) 2 => كائن (stdClass) عام "هاتف " => سلسلة "79871234567" (الطول = 11) سلسلة "نص" عامة => سلسلة "رسالة اختبار 3" (الطول = 37) سلسلة "تاريخ" عامة => سلسلة "22T14-08-2014:01:10" (الطول = 19) "النوع" العام => السلسلة "17" (الطول = 2)

أما أنا فإن «المجموع لا يتغير بتغير مواضع الألفاظ» (ج). ماذا وهمية، ماذا هيكل– لم نحقق هدفنا بعد! ولتحقيق ذلك، نحتاج إلى التأكد من أنه بدلاً من هذه الأسماء غير المفهومة يتم عرض اسمنا الأصلي رسالة. لكن المؤلف لا يعرف بعد كيفية تحقيق ذلك. ولذلك، فإن الشيء الوحيد الذي يمكننا القيام به هو التخلص من الحاوية الإضافية. بمعنى آخر، سوف نتأكد الآن من ذلك بدلاً من ذلك رسالةأصبح وهمية! للقيام بذلك، قم بتغيير الكائن كما يلي:

// إنشاء كائن لإرساله إلى الخادم $req = new Request(); $msg1 = رسالة جديدة(); $msg1->phone = "79871234567"; $msg1->text = "رسالة الاختبار 1"; $msg1->date = "21-07-2013T15:00:00.26"; $msg1->type = 15; $msg2 = رسالة جديدة(); $msg2->phone = "79871234567"; $msg2->text = "رسالة الاختبار 2"; $msg2->date = "22-08-2014T16:01:10"; $msg2->type = 16; $msg3 = رسالة جديدة(); $msg3->phone = "79871234567"; $msg3->text = "رسالة الاختبار 3"; $msg3->date = "22-08-2014T16:01:10"; $msg3->type = 17; $req->messageList = $msg1; $req->messageList = $msg2; $req->messageList = $msg3; $req->messageList = (object)$req->messageList;

ماذا لو كنا محظوظين وظهر الاسم الصحيح من الرسم البياني؟ للقيام بذلك، دعونا نلقي نظرة على المظروف الذي وصل:

79871234567 رسالة الاختبار 1 2013-07-21T15:00:00.26 15 79871234567 رسالة الاختبار 2 2014-08-22T16:01:10 16 79871234567 رسالة الاختبار 3 2014-08-22T16:01:10 17

نعم لم تحدث معجزة! وهمية- لن نفوز! جاء ل أرسل رسالة نصية قصيرةسيبدو الكائن في هذه الحالة كما يلي:

كائن (stdClass) عام "messageList" => كائن (stdClass) عام "BOGUS" => صفيف (الحجم = 3) 0 => كائن (stdClass) عام "هاتف" => سلسلة "79871234567" (الطول = 11) عام " نص" => سلسلة "رسالة اختبارية 1" (الطول = 37) "تاريخ" عام => سلسلة "21-07-2013T15:00:00.26" (الطول = 22) "نوع" عام => سلسلة "15" (الطول =2) 1 => كائن (stdClass) "هاتف" عام => سلسلة "79871234567" (الطول = 11) "نص" عام => سلسلة "رسالة اختبار 2" (الطول = 37) "تاريخ" عام => سلسلة " 22-08-2014T16:01:10" (الطول = 19) "النوع" العام => السلسلة "16" (الطول = 2) 2 => الكائن (stdClass) "الهاتف" العام => السلسلة "79871234567" (الطول = 11) "نص" عام => سلسلة "رسالة اختبارية 3" (الطول = 37) "تاريخ" عام => سلسلة "22T14-08-22T16:01:10" (الطول = 19) "نوع" عام => سلسلة " 17 بوصة (الطول = 2)

كما يقولون - "تقريبا"! في هذه الملاحظة (الحزينة بعض الشيء)، أقترح إنهاء الأمور ببطء واستخلاص بعض الاستنتاجات لأنفسنا.

8 الاستنتاج

وأخيراً وصلنا إلى هنا! دعنا نتعرف على ما يمكنك فعله الآن:

  • يمكنك كتابة ملف WSDL اللازم لخدمة الويب الخاصة بك؛
  • يمكنك بسهولة كتابة العميل الخاص بك الذي يمكنه التواصل مع الخادم عبر SOAP؛
  • يمكنك كتابة خادم خاص بك يتواصل مع العالم الخارجي عبر SOAP؛
  • يمكنك إرسال صفائف من نفس نوع الكائنات إلى الخادم من العميل الخاص بك (مع بعض القيود).

لقد حققنا أيضًا بعض الاكتشافات خلال بحثنا الصغير:

  • لا تقوم فئة SoapClient الأصلية بإجراء تسلسل بنيات البيانات من نفس النوع في XML بشكل صحيح؛
  • عند إجراء تسلسل لمصفوفة إلى XML، يتم إنشاء عنصر إضافي يسمى هيكل;
  • عند إجراء تسلسل لكائن إلى XML فإنه يقوم بإنشاء عنصر إضافي يسمى وهمية;
  • وهميةأقل شرا من هيكلنظرًا لأن المغلف أكثر إحكاما (لا تتم إضافة مساحات أسماء إضافية إلى رأس XML الخاص بالمغلف)؛
  • لسوء الحظ، لا تقوم فئة SoapServer تلقائيًا بالتحقق من صحة بيانات المغلف باستخدام مخطط XML الخاص بنا (ربما لا تقوم الخوادم الأخرى بذلك أيضًا).

الجزء الغنائي.

تخيل أنك نفذت أو تقوم بتنفيذ نظام معين يجب أن يكون متاحًا من الخارج. أولئك. هناك خادم معين تحتاج إلى التواصل معه. على سبيل المثال خادم الويب.

يمكن لهذا الخادم تنفيذ العديد من الإجراءات، والعمل مع قاعدة البيانات، وتنفيذ بعض طلبات الجهات الخارجية إلى خوادم أخرى، وإجراء بعض العمليات الحسابية، وما إلى ذلك. يعيش وربما يتطور حسب السيناريو المعروف لديه (أي حسب سيناريو المطورين). ليس من المثير للاهتمام أن يتواصل شخص ما مع مثل هذا الخادم، لأنه قد لا يتمكن/يريد تقديم صفحات جميلة تحتوي على صور ومحتويات أخرى سهلة الاستخدام. وهي مكتوبة وتعمل على العمل وتقديم البيانات عندما يطلب منها ذلك، دون القلق من أنها قابلة للقراءة البشرية، فسيتعامل معها العميل بنفسه.

يمكن للأنظمة الأخرى، التي تصل إلى هذا الخادم، أن تتخلص بالفعل من البيانات الواردة من هذا الخادم وفقًا لتقديرها الخاص - معالجة وتجميع وإصدار لعملائها، وما إلى ذلك.

حسنًا، أحد خيارات التواصل مع هذه الخوادم هو SOAP. بروتوكول تبادل الرسائل SOAP XML.

الجزء العملي.

خدمة الويب (هذا هو اسم ما يقدمه الخادم وما يستخدمه العملاء) تجعل من الممكن التواصل مع الخادم برسائل منظمة بشكل واضح. الحقيقة هي أن خدمة الويب لا تقبل أي بيانات. سوف تستجيب خدمة الويب بخطأ لأي رسالة لا تتوافق مع القواعد. بالمناسبة، سيكون الخطأ أيضًا في شكل xml ببنية واضحة (وهذا غير صحيح فيما يتعلق بنص الرسالة).

WSDL (لغة وصف خدمات الويب). القواعد التي يتم من خلالها تكوين الرسائل لخدمة الويب موصوفة أيضًا باستخدام XML ولها أيضًا بنية واضحة. أولئك. إذا كانت خدمة الويب توفر القدرة على استدعاء طريقة ما، فيجب أن تسمح للعملاء بمعرفة المعلمات المستخدمة لهذه الطريقة. إذا كانت خدمة الويب تتوقع سلسلة للطريقة 1 كمعلمة ويجب تسمية السلسلة باسم Param1، فسيتم تحديد هذه القواعد في وصف خدمة الويب.

ليس فقط الأنواع البسيطة، ولكن أيضًا الكائنات ومجموعات الكائنات يمكن تمريرها كمعلمات. يتلخص وصف الكائن في وصف كل مكون من مكونات الكائن. إذا كان الكائن يتكون من عدة حقول، فسيتم وصف كل حقل ونوعه واسمه (ما هي القيم المحتملة). يمكن أن تكون الحقول أيضًا من النوع المعقد، وهكذا حتى ينتهي وصف الأنواع بأنواع بسيطة - سلسلة، منطقية، رقم، تاريخ... ومع ذلك، قد تكون بعض الأنواع المحددة بسيطة، فمن المهم أن يكون العملاء يمكن أن نفهم ما هي القيم التي قد تحتوي عليها.

بالنسبة للعملاء، يكفي معرفة عنوان url الخاص بخدمة الويب، وسيكون wsdl قريبًا دائمًا، حيث يمكنك من خلاله الحصول على فكرة عن الأساليب ومعلماتها التي توفرها خدمة الويب هذه.

ما هي مزايا كل هذه الأجراس والصفارات:

  • في معظم الأنظمة، يتم وصف الأساليب والأنواع تلقائيًا. أولئك. يحتاج المبرمج الموجود على الخادم فقط إلى الإشارة إلى أنه يمكن استدعاء هذه الطريقة من خلال خدمة ويب، وسيتم إنشاء وصف wsdl تلقائيًا.
  • الوصف ذو البنية الواضحة يمكن قراءته من قبل أي عميل صابون. أولئك. مهما كانت خدمة الويب، سوف يفهم العميل البيانات التي تتلقاها خدمة الويب. باستخدام هذا الوصف، يمكن للعميل بناء البنية الداخلية الخاصة به لفئات الكائنات، ما يسمى. ملزم" و. ونتيجة لذلك، يجب على المبرمج الذي يستخدم خدمة الويب أن يكتب شيئًا مثل (الكود الكاذب):

    NewUser:=TSoapUser.Create("Vasya"،"Pupkin"، "admin")؛ Soap.AddUser(NewUser);

  • التحقق التلقائي.

    • التحقق من صحة XML. يجب أن يكون ملف xml مُصاغًا بشكل جيد. ملف XML غير صالح - حدث خطأ على الفور للعميل، دعه يحل المشكلة.
    • التحقق من صحة المخطط. يجب أن يكون لـ XML بنية معينة. XML لا يتطابق مع المخطط - حدث خطأ على الفور للعميل، دعه يحل المشكلة.
    • يتم التحقق من البيانات بواسطة خادم الصابون بحيث تتطابق أنواع البيانات والقيود مع الوصف.
  • يمكن تنفيذ التخويل والمصادقة باستخدام طريقة منفصلة. محليا. أو باستخدام ترخيص http.
  • يمكن أن تعمل خدمات الويب عبر بروتوكول الصابون وعبر http، أي من خلال طلبات الحصول. أي إذا كانت المعلمات عبارة عن بيانات بسيطة (بدون بنية)، فيمكنك ببساطة الاتصال بالموقع المعتاد www.site.com/users.asmx/GetUser?Name=Vasia أو النشر. ومع ذلك، هذا ليس في كل مكان وليس دائما.
  • ... انظر على ويكيبيديا

هناك أيضًا الكثير من العيوب:

  • حجم الرسالة كبير بشكل غير معقول. حسنًا، طبيعة XML هنا تجعل التنسيق زائدًا عن الحاجة، وكلما زاد عدد العلامات، زادت المعلومات عديمة الفائدة. بالإضافة إلى الصابون يضيف التكرار. بالنسبة لأنظمة الإنترانت، تكون مشكلة حركة المرور أقل حدة من الإنترنت، لذا فإن الطلب على الصابون للشبكات المحلية أكثر طلبًا، ولا سيما لدى Sharepoint خدمة ويب للصابون يمكنك من خلالها التواصل بنجاح (وبعض القيود).
  • يمكن أن يؤدي تغيير وصف خدمة الويب تلقائيًا إلى تعطيل كافة العملاء. حسنًا، هذا هو الحال بالنسبة لأي نظام، إذا لم يكن التوافق مع الأساليب القديمة مدعومًا، فسيسقط كل شيء...
  • ليس ناقصا، ولكن العيب. يجب أن تكون كافة استدعاءات الطريقة ذرية. على سبيل المثال، عند العمل مع قاعدة بيانات، يمكننا بدء معاملة، وتنفيذ عدة استعلامات، ثم التراجع أو الالتزام. لا توجد معاملات في الصابون. طلب واحد، إجابة واحدة، انتهت المحادثة.
  • قد يكون التعامل مع وصف ما هو موجود على جانب الخادم (هل تم وصف كل شيء بشكل صحيح؟) وما هو موجود على العميل (ما تم وصفه لي هنا؟) أمرًا صعبًا للغاية. كانت هناك عدة مرات عندما اضطررت إلى التعامل مع جانب العميل وإقناع مبرمج الخادم بأن بياناته تم وصفها بشكل غير صحيح، لكنه لم يتمكن من فهم أي شيء عنها على الإطلاق، لأن التوليد التلقائي ولا ينبغي له ذلك، إنها مسألة برمجة. والخطأ، بطبيعة الحال، كان في كود الطريقة، لكن المبرمج ببساطة لم يتمكن من رؤيته.
  • تظهر الممارسة أن مطوري خدمات الويب بعيدون جدًا عن الأشخاص الذين يستخدمون خدمات الويب هذه. استجابة لأي طلب (صالح من الخارج)، قد يأتي خطأ غير مفهوم "خطأ 5. كل شيء سيء". كل هذا يتوقف على ضمير المطورين :)
  • أنا متأكد من أنني مازلت لا أتذكر شيئًا ما..

على سبيل المثال، هناك خدمة ويب مفتوحة بيلافيا:

  • http://86.57.245.235/TimeTable/Service.asmx - نقطة الدخول، يوجد أيضًا وصف نصي للطرق لمطوري الطرف الثالث.
  • http://86.57.245.235/TimeTable/Service.asmx?WSDL - وصف wsdl لأساليب وأنواع البيانات المستلمة والمرتجعة.
  • http://86.57.245.235/TimeTable/Service.asmx?op=GetAirportsList - وصف طريقة محددة مع مثال لنوع طلب XML واستجابة XML.

يمكنك إنشاء طلب وإرساله يدويًا مثل:

POST /TimeTable/Service.asmx HTTP/1.1 المضيف: 86.57.245.235 نوع المحتوى: نص/xml؛ charset=utf-8 طول المحتوى: طول SOAPAction: "http://webservices.beavia.by/GetAirportsList" رو

سيأتي الجواب:

HTTP/1.1 200 OK التاريخ: الإثنين، 30 سبتمبر 2013 00:06:44 بتوقيت جرينتش الخادم: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 4.0.30319 التحكم في ذاكرة التخزين المؤقت: خاص، الحد الأقصى -age=0 نوع المحتوى: text/xml; مجموعة الأحرف = utf-8 طول المحتوى: 2940

ملاحظة: في السابق، تم فتح خدمة الويب الخاصة بشركة Aeroflot، ولكن بعد إضافة 1C لدعم الصابون إلى 8ku، نجحت مجموعة من مختبري الإصدار التجريبي من 1C في تثبيته. والآن تغير شيء ما هناك (لا أعرف العنوان، يمكنك البحث عنه إذا كنت مهتمًا).
إخلاء المسؤولية عن ZZY. لقد تحدث على المستوى اليومي. يمكنك ركلة.

لن أتطرق إلى مسألة ما هو عليه خدمات الويبولماذا هناك حاجة إليها. هناك الكثير من المقالات حول هذا الموضوع على الإنترنت. سأحاول فقط أن أعرض بإيجاز مدى سهولة إنشاء عميل لأي خدمة ويب في PHP.

إعدادات

للاستخدام صابونفي PHP تحتاج إلى توصيل وحدة SOAP (المضمنة في توزيع php5). في نظام التشغيل Windows، يتم ذلك ببساطة - تحتاج إلى الإضافة (أي الإضافة، نظرًا لأن هذا السطر لم يتم التعليق عليه فحسب، بل إنه مفقود تمامًا) في php.ini:
ملحق=php_soap.dll

لا تنس إعادة تشغيل الخادم إذا كان لديك PHP مثبتًا كوحدة نمطية.


إنشاء عميل SOAP من مستند WSDL

عادةً ما يتم إنشاء عميل SOAP عن طريق وثيقة WSDL، وهو مستند XML بتنسيق محدد يصف خدمة ويب معينة بشكل كامل. للحصول على تفاصيل حول WSDL، أحيلك إلى موقع اتحاد W3C - http://www.w3.org/TR/2005/WD-wsdl20-soap11-binding-20050510/.

الشيء الرئيسي الذي تحتاج إلى معرفته لإنشاء عميل لخدمة ويب هو معرفة عنوان URL الخاص بمستند WSDL الخاص به.
على سبيل المثال، لنأخذ خدمة الويب "سعر صرف العملة" من موقع xmethods.com. عنوان خدمة الويب هذه، التي تسمح لك بتلقي أسعار الصرف عبر الإنترنت، هو http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl.

النقطة الثانية المهمة هي أنه من وصف خدمة الويب من الضروري الحصول على معلومات حول الطرق التي توفرها هذه الخدمة، وما هي المعلمات التي يجب أن نمررها إليها كقيم إدخال (تشبه إلى حد كبير استدعاء دالة أو فئة PHP عادية طريقة). عادة ما يتم تضمين هذه المعلومات في وصف الخدمة على موقعها على الانترنت. توفر خدمة الويب الخاصة بنا للحصول على أسعار الصرف طريقة getRate()، والتي يتم تمرير رموز العملات إليها كوسيطات.

وأخيرًا، من المهم معرفة ما يمكن توقعه كإجابة: كم عدد القيم، أي نوع، وما إلى ذلك. ويمكن الحصول على هذا أيضًا من الوصف.
ونتيجة لذلك، تبين أن الكود بسيط للغاية ومضغوط، وهو أولي تقريبًا:

// استخدام خدمة الويب
// "سعر صرف العملة" من xmethods.com

// إنشاء عميل SOAP من مستند WSDL
$client = new SoapClient("http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl");

// أرسل طلب SOAP واحصل على النتيجة
$result = $client->getRate("us", "russia");

صدى 'سعر صرف الدولار الحالي: '، نتيجة $، 'روبل'؛
?>

كما ترون من التعليمات البرمجية، تحتاج إلى تمرير عنوان URL لمستند WSDL إلى مُنشئ فئة SoapClient واستلام كائن للعمل مع خدمة الويب المطلوبة. ثم يتم استدعاء طريقة لهذا الكائن، واسمها هو نفس اسم طريقة خدمة الويب نفسها. هذه الطريقة ترجع النتيجة التي نريدها.

لذلك، يوضح هذا المثال البسيط مبدأ بناء عميل SOAP لخدمات الويب في PHP. ومع ذلك، في التطبيق الحقيقي، لا يزال هناك الكثير مما يجب الاهتمام به، لا سيما حقيقة أنه عند استدعاء خدمة الويب، قد تكون غير متاحة مؤقتًا أو تعرض خطأ. يقترح بوضوح استخدام كتلة حاول / قبض / رمي :)

(بي إتش بي 5 >= 5.0.1)

SoapClient::SoapClient — مُنشئ SoapClient

حدود

com.wsdl

معرف الموارد المنتظم (URI) الخاص بـ WSDLملف أو باطلإذا كنت تعمل في غير WSDLوضع.

أثناء التطوير، قد يتم تعطيل التخزين المؤقت لـ WSDL عن طريق استخدام ملف Soap.wsdl_cache_ttlإعداد php.ini وإلا فإن التغييرات التي تم إجراؤها على ملف WSDL لن يكون لها أي تأثير حتى Soap.wsdl_cache_ttlمنتهي الصلاحية.

خيارات

مجموعة من الخيارات. إذا كنت تعمل في وضع WSDL، تكون هذه المعلمة اختيارية. إذا كنت تعمل في وضع غير WSDL، فإن موقعو أورييجب تعيين الخيارات، حيث موقعهو عنوان URL لخادم SOAP لإرسال الطلب إليه و أوريهي مساحة الاسم الهدف لخدمة SOAP.

ال أسلوبو يستخدمتعمل الخيارات فقط في وضع غير WSDL. في وضع WSDL، تأتي هذه الملفات من ملف WSDL.

ال Soap_versionيحدد الخيار ما إذا كان سيتم استخدام SOAP 1.1 (الافتراضي) أو عميل SOAP 1.2.

بالنسبة لمصادقة HTTP، فإن تسجيل الدخولو كلمة المروريمكن استخدام الخيارات لتوفير بيانات الاعتماد. لإجراء اتصال HTTP من خلال خادم وكيل، الخيارات proxy_host, proxy_port, proxy_loginو proxy_passwordمتوفرة أيضًا. لاستخدام مصادقة شهادة عميل HTTPS local_certو عبارة المرورخيارات. قد يتم توفير المصادقة في المصادقةخيار. قد تكون طريقة المصادقة إما SOAP_AUTHENTICATION_BASIC(الافتراضي) أو SOAP_AUTHENTICATION_DIGEST.

ال ضغطيسمح الخيار باستخدام ضغط طلبات واستجابات HTTP SOAP.

ال التشفيريحدد الخيار ترميز الأحرف الداخلي. لا يغير هذا الخيار ترميز طلبات SOAP (يكون دائمًا utf-8)، ولكنه يحول السلاسل إليه.

ال يتعقبيتيح الخيار تتبع الطلب حتى يمكن تعقب الأخطاء. هذا افتراضيا ل خطأ شنيع

ال com.classmapيمكن استخدام الخيار لتعيين بعض أنواع WSDL لفئات PHP. يجب أن يكون هذا الخيار عبارة عن مصفوفة تحتوي على أنواع WSDL كمفاتيح وأسماء فئات PHP كقيم.

تعيين المنطقية يتعقبيتيح الخيار استخدام الطرق SoapClient->__getLastRequest و SoapClient->__getLastRequestHeaders و SoapClient->__getLastResponse و SoapClient->__getLastResponseHeaders .

ال استثناءاتالخيار هو قيمة منطقية تحدد ما إذا كانت أخطاء الصابون تؤدي إلى استثناءات من النوع SoapFault .

ال انتهى وقت محاولة الاتصاليحدد الخيار مهلة بالثواني للاتصال بخدمة SOAP. لا يحدد هذا الخيار مهلة للخدمات ذات الاستجابات البطيئة. للحد من وقت انتظار انتهاء المكالمات، يتوفر الإعداد default_socket_timeout.

ال خريطة الكتابةالخيار هو مجموعة من تعيينات النوع. تعيين النوع عبارة عن مصفوفة تحتوي على مفاتيح أكتب اسم, type_ns(مساحة الاسم URI)، from_xml(رد الاتصال يقبل معلمة سلسلة واحدة) و to_xml(رد الاتصال يقبل معلمة كائن واحدة).

ال Cache_wsdlالخيار هو واحد من WSDL_CACHE_NONE, WSDL_CACHE_DISK, WSDL_CACHE_MEMORYأو WSDL_CACHE_BOTH.

ال وكيل المستخدميحدد الخيار السلسلة المراد استخدامها فيها وكيل المستخدم header.

ال Stream_contextالخيار هو للسياق.

ال سماتالخيار هو قناع بت SOAP_SINGLE_ELEMENT_ARRAYS, SOAP_USE_XSI_ARRAY_TYPE, SOAP_WAIT_ONE_WAY_CALLS.

ال حافظ على حياتكالخيار هو قيمة منطقية تحدد ما إذا كان سيتم إرسال الاتصال: البقاء على قيد الحياةرأس أو الاتصال: قريب .

سجل التغيير

إصدار وصف
5.4.0 جديد حافظ على حياتكخيار.

أمثلة

مثال 1 SoapClient::SoapClient() مثال

$client = new SoapClient("some.wsdl");

$client = new SoapClient ("some.wsdl" , array("soap_version" => SOAP_1_2 ));

$client = new SoapClient ("some.wsdl" , array("login" => "some_name" ,
"كلمة المرور" => "some_password" ));

$client = new SoapClient ("some.wsdl" , array("proxy_host" => "localhost" ,
"proxy_port" => 8080 ));

$client = new SoapClient ("some.wsdl" , array("proxy_host" => "localhost" ,
"proxy_port" => 8080،
"proxy_login" => "some_name" ,
"proxy_password" => "some_password" ));

$client = new SoapClient("some.wsdl" , array("local_cert" => "cert_key.pem" ));

$client = new SoapClient (null , array("location" =>
"uri" => "http://test-uri/" ));

$client = new SoapClient (null , array("location" => "http://localhost/soap.php" ,
"أوري" => "http://test-uri/" ,
"النمط" => SOAP_DOCUMENT ,
"استخدام" => SOAP_LITERAL ));

$client = new SoapClient("some.wsdl" ,
array("compression" => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP ));

$server = new SoapClient("some.wsdl" , array("encoding" => "ISO-8859-1" ));

فئة ماي بوك(
العنوان العام $؛
المؤلف $ العام ؛
}

$server = new SoapClient ("books.wsdl" , array("classmap" => array("book" => "MyBook" )));

?>

كريس جوناواردينا

لمراقبة مكالمات SOAP داخل وخارج خادم يونكس:

Sudo tcpdump -nn -vv -A -s 0 -i eth0 dst أو src host xxx.xxx.xxx.xxx والمنفذ 80

واستخدم دائمًا "cache_wsdl" => WSDL_CACHE_NONE

svenr في selfhtml dot org

خيار "classmap" هو في الواقع تعيين من "ComplexType" المستخدم داخل SOAP إلى فئات PHP الخاصة بك.

لا تخلط بين أسماء علامات XML التي تم إرجاعها لطلبك وبين هذه الأنواع المعقدة. SOAP يسمح لهم بأن يكونوا مختلفين.

كان لدي شيء مثل هذا:
...


فوبار

TagName ليس هو المفتاح الذي تريد وضعه في خريطة الفصل الدراسي الخاصة بك، عليك أن تعرف اسم ComplexType الذي يشير إليه TagName. هذه المعلومات موجودة داخل مورد WSDL.

بولوفيتوربال في جوجل دوت كوم

عند استخدام الشهادات، في المعلمة "local_cert"، استخدم محتويات الملف، وليس اسم الملف.

عميل صابون جديد("http://localhost/index.php?wsdl ", array("local_cert"=>file_get_contents("./key.pem"),"passphrase"=>"password"));

في PHP، يمكنك الحصول على خصائص خاصة محددة في الفئات التي تستخدمها في خريطة الفصل الخاصة بك. لذا، إذا قمت بإنشاء خاصية خاصة $foo في فصلك الدراسي، وكان عنصر SOAP يحتوي على عنصر فرعي ، سيتم تعيين محتويات $foo على محتويات . بهذه الطريقة يمكنك التحكم في الوصول إلى الخصائص الموجودة في فصولك الدراسية.

(ملاحظة: هذا لا يعمل في HPHP الخاص بفيسبوك).

Willem dot stuursma في hyves dot nl

إذا كنت تريد استخدام الفئات في مساحة اسم مختلفة في خريطة الفصل الخاصة بك، فما عليك سوى استخدام الشرطة المائلة العكسية في اسم الفئة المستهدفة.

مثال:
$classmap = array("result" => "MyNamespace\\Result" );
?>

تحتاج إلى تحديد الخط المائل العكسي مرتين لأنه حرف الهروب في السلاسل.

سيمونلانغ في GMX نقطة الفصل

مثال لعميل الصابون مع مصادقة HTTP عبر وكيل:

عميل الصابون الجديد(
"الخدمة.wsdl"،
مجموعة مصفوفة(
// أشياء للتطوير.
"تتبع" => 1 ,
"الاستثناءات" => صحيح،
"cache_wsdl" => WSDL_CACHE_NONE ,
"الميزات" => SOAP_SINGLE_ELEMENT_ARRAYS ,

// بيانات اعتماد المصادقة لطلب SOAP.
"تسجيل الدخول" => "اسم المستخدم" ,
"كلمة المرور" => "كلمة المرور" ,

// عنوان URL الوكيل.
"proxy_host" => "example.com" , // لا تقم بإضافة المخطط هنا (http أو https). لن ينجح الأمر.
"proxy_port" => 44300،

// بيانات اعتماد المصادقة للوكيل.
"proxy_login" => NULL ,
"proxy_password" => NULL ,
);
?>
لم ينجح توفير عنوان URL لملف WSDL على الخادم البعيد (والذي يكون محميًا أيضًا بمصادقة HTTP). لقد قمت بتنزيل WSDL وقمت بتخزينه على الخادم المحلي.

عساف ميلر

تكوين صابون php .net يعمل بشكل كامل:
ملحوظات
1. يجب أن يعمل web.config على خادم .net مع رابط http الأساسي.
2. يجب تمرير معلمات وظائف الصابون على النحو التالي:
المصفوفة ("parm1_name"=>"parm1_value"،
"parm2_name"=>"parm2_value"...)

header("نوع المحتوى: نص/عادي");

يحاول(
خيارات $ = صفيف (
"soap_version" => SOAP_1_1 ,
"الاستثناءات" => صحيح،
"تتبع" => 1 ,
"cache_wsdl" => WSDL_CACHE_NONE
);
$client = SoapClient الجديد ( "http://www.example.com/end_point.wsdl"، خيارات $)؛

) صيد (استثناء $e ) (
صدى صوت "

خطأ استثناء!

" ;
صدى $e -> getMessage();
}

صدى "تشغيل HelloWorld:" ؛

يحاول(
$response = $client -> HelloWorld();

}
قبض (استثناء $e)
{
echo "تم اكتشاف استثناء: " , $e -> getMessage (), "\n" ;
}

Print_r($response);
?>
حظ سعيد!
عساف.

faebu في faebu نقطة ch

أواجه نفس المشكلات عند محاولة تحميل ملف WDSL المحمي بواسطة مصادقة http الأساسية، حيث يتم استخدام تسجيل الدخول وكلمة المرور للمعلمات فقط للطلب ولكن ليس عند قراءة ملف wdsl. أستخدم الحل البديل التالي عن طريق التنزيل ملف xml إلى موقع غير محمي على الخادم الخاص بي. يرجى ملاحظة أن هذا لا يدعم أي نوع من التخزين المؤقت.

تقوم فئة SoapAuthClient بتوسيع SoapClient (
/**
* نظرًا لأن حزمة PHP SOAP لا تدعم المصادقة الأساسية
* يقوم هذا الفصل بتنزيل ملف WDSL باستخدام حزمة cURL و
* يقوم بإنشاء نسخة محلية من wdsl على الخادم الخاص بك.
*تأكد من توفير المعلمة الإضافية التالية في ملف
*$optionsArray:
* wdsl_local_copy => صحيح
*/

خاص $cache_dir = "/home/example/htdocs/cache/" ;
خاص $cache_url = "http://www.example.com/cache/";

الدالة SoapAuthClient ($wdsl, $options) (
إذا (isset($options [ "wdsl_local_copy" ]) &&
خيارات $ [ "wdsl_local_copy" ] == صحيح &&
isset($options ["تسجيل الدخول"]) &&
isset($options ["كلمة المرور" ])) (

ملف $ = md5(uniqid()). ".xml" ؛

إذا (($fp = fopen ($this -> Cache_dir . $file , "w" )) == false ) (
رمي استثناء جديد ( ""تعذر إنشاء ملف WDSL محلي ("". $هذا -> Cache_dir . ملف $. ")")؛
}

$ch = curl_init();
$credit = ($options["login"]. ": . $options["password" ]);
curl_setopt($ch, CURLOPT_URL, $wdsl);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt ($ch، CURLOPT_USERPWD، $credit)؛
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt ($ch، CURLOPT_FILE، $fp)؛
إذا (($xml = curl_exec ($ch )) === false ) (
//curl_Close($ch);
fClose($fp);
إلغاء الارتباط ($this -> Cache_dir . $file );

طرح استثناء جديد(curl_error($ch));
}

Curl_Close($ch);
fClose($fp);
$wdsl = $this -> Cache_url . ملف $؛
}

Unset($options [ "wdsl_local_copy" ]);
unset($options [ "wdsl_force_local_copy" ]);

صدى $wdsl ;
الأصل :: __construct ($wdsl, $options);

إلغاء الارتباط ($this -> Cache_dir . $file );
}
}
?>

تاتوفيبا في جوجل دوت كوم

مرحبا الناس!

تلميح للمطورين:

عند برمجة بعض خوادم الصابون، قم بتعيين التوجيه "soap.wsdl_cache_enabled" في ملف php.ini إلى 0:

Soap.wsdl_cache_enabled=0

وإلا فإنه سيعطي مجموعة من الأخطاء الغريبة التي تشير إلى أن wsdl الخاص بك غير صحيح أو مفقود.

القيام بذلك سيوفر لك الكثير من الألم غير المجدي.

تيتان في phpdevshell dot org

تجدر الإشارة إلى أنه إذا تلقيت خطأ إرجاع: "لم يتم تعيين مرجع الكائن إلى مثيل كائن." قد يكون هذا بسبب شيء بسيط مثل تمرير المعلمات غير الصحيحة. عندما تنظر إلى ملف XML هذا:



خيط
dateTime
dateTime

يجب أن يبدو الكود الخاص بك كما يلي:

يحاول (
خيارات $ = صفيف (
"soap_version" => SOAP_1_2 ,
"الاستثناءات" => صحيح،
"تتبع" => 1 ,
"cache_wsdl" => WSDL_CACHE_NONE
);
$client = SoapClient الجديد ( "http://example.com/doc.asmx?WSDL"، خيارات $)؛
// لاحظ مكان وجود علامتي "Get" و"request" في ملف XML
$results = $client -> Get (array("request" =>array("CustomerId" => "1234" )));
) صيد (استثناء $e ) (
صدى صوت "

خطأ استثناء!

" ;
صدى $e -> getMessage();
}

$results = $client -> Get (array("request" =>array("CustomerId" => "842115" )));
?>

إذا كان ملف WSDL الخاص بك يحتوي على معلمة من النوع base64Binary، فيجب ألا تستخدم base64_encode() عند تمرير vars الخاص بك. عند إجراء الطلب، تقوم مكتبة SOAP تلقائيًا بترميز بياناتك باستخدام base64، وإلا فسوف تقوم بتشفيرها مرتين.

مقتطف WSDL:

سلسلة $ = "data_you_want_to_send___like_xml_in_soap";
$soap_data = المصفوفة(
"فو" => "شريط" ,
//"content" => base64_encode($string) // لا تفعل هذا
"المحتوى" => سلسلة $ // افعل هذا
);
$response = $client -> إرسال ($soap_data );
?>

ماركوفتووت في هوتميل دوت كوم

كوني جديدًا على SOAP، كنت أبحث لفترة من الوقت لأكتشف سبب حصول رسالتي على استجابة في واجهة SoapUI، ولكن ليس باستخدام كود php الخاص بي. الخدمة المحددة التي كنت أتناولها تعطي قبول HTTP 202 عند النجاح (بدون استجابة)، ولكنها تُرجع رسالة SOAP عند وجود أخطاء.

الموقف:
باستخدام اتصال عميل (مصادق عليه) وملف WDSL، لا تعطي مكالمات SOAP من النوع "One-Way" رأس استجابة، على الرغم من توقع الاستجابة.

حل:
عند استدعاء مُنشئ العميل، قم بتعيين SOAP_WAIT_ONE_WAY_CALLS في $options["features"].

تيم في tdinternet دوت كوم

يبدو أن PHP 5.2.11 ليس انتقائيًا جدًا بشأن صحة WSDL.

كان عملاء SOAP الآخرون يشكون من مشكلات المخطط ومساحة الاسم، بينما كان SoapClient الخاص بـ PHP يعمل بشكل جيد تمامًا. ومع ذلك، أدى إصلاح هذه المشكلات للعملاء الآخرين إلى تعطيل SoapClient الخاص بـ PHP إلى النقطة التي أصبحت فيها الكائنات التي يتم تمريرها إلى طريقة SOAP عبارة عن صفائف فارغة على جانب الخادم.

الدرس المستفاد: كانت بعض العناصر مسبوقة بـ xsd: والبعض الآخر لم يكن كذلك - تأكد تمامًا من أن WSDL الخاص بك صحيح ومتسق (أنا أستخدم WSDL_Gen.php المعدل).

جيمس دوت إليس في جوجل دوت كوم

كنت أواجه مشكلات في الحصول على استجابات من خادم Coldfusion SOAP، مع عدم وجود مشكلات واضحة في SoapClient المستخدم.

في النهاية وجدت أن الخادم كان يقبل فقط طلبات SOAP 1.1 وليس 1.2. لست متأكدًا مما إذا كان هذا هو إعداد Coldfusion على مستوى النظام ولكن إذا وصلت إلى نفس الجدار، فحاول تعيين خيار SoapClient "soap_version" على SOAP_1_1 الثابت (وهو الإعداد الافتراضي ولكن كان الإعداد الافتراضي هو 1.2 حيث تم إعادة استخدام العميل لخدمة أخرى )

ajcartmell في فونانت دوت كوم

يبدو أن هناك مشكلة في تحديد سلاسل فارغة لخيارات proxy_host وproxy_port في الإصدارات الحديثة من PHP (من إصدار أحدث من 5.2.9، ويساوي أو يسبق 5.2.11).

يؤدي توفير قيم سلسلة فارغة لـ proxy_host وproxy_port إلى حدوث أخطاء من النوع "لم يتم العثور على المضيف": يعمل توفير NULL أو FALSE بشكل جيد.

بهارجاف دوت خاتانا في جوجل دوت كوم

لقد استغرق الأمر أكثر من أسبوع لمعرفة كيفية تنفيذ رؤوس WSSE (أمان خدمة الويب) في PHP SOAP الأصلي. لا يوجد الكثير من الموارد المتاحة في هذا الشأن، لذا فكرنا في إضافتها هنا لفائدة المجتمع.

الخطوة 1: قم بإنشاء فئتين لإنشاء بنية لرؤوس WSSE

فئة CLWSSEauth (
اسم المستخدم الخاص $؛
كلمة المرور الخاصة $؛
وظيفة __بناء ($ اسم المستخدم، كلمة المرور $) (
$this -> اسم المستخدم = $username ;
$هذا -> كلمة المرور = كلمة المرور $؛
}
}

فئة clsWSSEToken(
خاص $UsernameToken؛
الدالة __بناء ($innerVal)(
$this -> UsernameToken = $innerVal ;
}
}
?>
الخطوة 2: إنشاء متغيرات الصابون لاسم المستخدم وكلمة المرور

اسم المستخدم $ = 1111 ;
كلمة المرور $ = 1111 ;

// تحقق مع مزود الخدمة الخاص بك من مساحة اسم الأمان التي يستخدمها.
$ستروسنس = "http://schemas.xmlsoap.org/ws/2002/07/secext";

$objSoapVarUser = new SoapVar($username, XSD_STRING, NULL, $strWSSENS, NULL, $strWSSENS);
$objSoapVarPass = new SoapVar($password, XSD_STRING, NULL, $strWSSENS, NULL, $strWSSENS);
?>
الخطوة 3: إنشاء كائن لفئة المصادقة وتمرير الصابون var

$objWSSEAuth = new clsWSSEAuth ($objSoapVarUser , $objSoapVarPass );
?>
الخطوة 4: إنشاء SoapVar خارج كائن فئة المصادقة

$objSoapVarWSSEuth= new SoapVar ($objWSSEAuth , SOAP_ENC_OBJECT , NULL , $strWSSENS , "UsernameToken" , $strWSSENS );
?>
الخطوة 5: إنشاء كائن لفئة الرمز المميز

$objWSSEToken = new clsWSSEToken ($objSoapVarWSSEAuth );
?>
الخطوة 6: إنشاء SoapVar من كائن فئة Token

$objSoapVarWSSEToken= new SoapVar ($objWSSEToken, SOAP_ENC_OBJECT, NULL, $strWSSENS, "UsernameToken", $strWSSENS);
?>
الخطوة 7: إنشاء SoapVar لعقدة "الأمان".

$objSoapVarHeaderVal=new SoapVar ($objSoapVarWSSEToken, SOAP_ENC_OBJECT, NULL, $strWSSENS, "Security", $strWSSENS);
?>
الخطوة 8: إنشاء كائن رأس من ملف الأمان Soapvar

$objSoapVarWSSEHeader= new SoapHeader ($strWSSENS , "Security" , $objSoapVarHeaderVal , true , "http://abce.com");

// المعلمة الثالثة هنا تجعل "mustUnderstand=1
// تنشئ المعلمة الرابعة "actor = "http://abce.com ""
?>
الخطوة 9: إنشاء كائن Soap Client

$objClient = new SoapClient ($WSDL, $arrOptions);
?>
الخطوة 10: قم بتعيين الرؤوس لكائن عميل الصابون

$objClient -> __setSoapHeaders (array($objSoapVarWSSEHeader ));
?>
الخطوة 11: النداء الأخير للطريقة

$objResponse = $objClient -> __soapCall ($strMethod , $requestPayloadString );
?>

بيتر في webacoustics دوت كوم

لقد وجدت أن جلب WSDL يفشل عند استخدام المصادقة الأساسية في عميل الصابون. لذلك قمت بتنفيذ الحل البديل التالي باستخدام wget. أدرك أن wget قد لا يكون خيارًا لبعض البيئات، وفي هذه الحالة سيكون cURL هو ثاني أبسط شيء.

$wsdl = get_wsdl ( "https://example.com/soap/service?wsdl");
$this -> client = new SoapClient ($wsdl , array("user" => "someuser" , "password" => "somepassword" ));

وظيفة خاصة get_wsdl ($url) (
عالمي $g؛
$url = escapeshellarg($url);
$cache_file = "/tmp/soap.wsdl." . MD5($url);

// جلب wsdl جديد فقط كل ساعة
إذا (! file_exists ($cache_file) || filectime ($cache_file)< time () - 3600 ) {
$agent = escapeshellarg("--user-agent=($g["useragent"])");
mwexec("wget ​​​​--quiet --timeout=5 ( $agent ) --no-check-certificate --output-document=( $cache_file ) ( $url ) " );
إذا (! file_exists ($cache_file )) (
طرح استثناء جديد ("تعذر تحميل WSDL على ( $url )" );
}
}
يعود
$cache_file؛
}
?>

ميلتير في ميلتير دوت كوم

إلى أولئك الذين يتقاتلون مع خوادم بروكسي NTLM المصادق عليها، إليك الحل الذي أستخدمه ATM:

/**
* تابع لـ SoapClient مع دعم مصادقة وكيل ntlm
*
* @المؤلف ميلتير
*
*/
تمتد الفئة NTLM_SoapClient إلى SoapClient (

الوظيفة العامة __construct ($wsdl, $options = array()) (
إذا (فارغ($options ["proxy_login" ]) || فارغ($options ["proxy_password" ])) طرح استثناء جديد ( "تسجيل الدخول وكلمة المرور مطلوبان لمصادقة NTLM!");
$this -> proxy_login = $options [ "proxy_login" ];
$this -> proxy_password = $options [ "proxy_password" ];
$this -> proxy_host = (فارغ($options [ "proxy_host" ]) ؟ "المضيف المحلي": خيارات $[ "proxy_host"]);
$هذا-> proxy_port= (فارغة(خيارات $[ "proxy_port"]) ? 8080 : خيارات $[ "proxy_port"]);
الأبوين:: __بناء($wsdl, خيارات $);
}

/**
* استدعاء عنوان url باستخدام الضفيرة مع مصادقة ntlm
*
*param سلسلة $url
* @param سلسلة بيانات $
* @ سلسلة العودة
* @throws SoapFault على خطأ في اتصال الضفيرة
*/
وظيفة محميةcallCurl($url, بيانات $) {
مقبض $= curl_init();
curl_setopt(مقبض $, CURLOPT_HEADER, خطأ شنيع);
curl_setopt(مقبض $, CURLOPT_URL, $url);
curl_setopt(مقبض $, CURLOPT_FAILONERROR, حقيقي);
curl_setopt(مقبض $, CURLOPT_HTTPHEADER،مجموعة مصفوفة("عميل PHP SOAP-NTLM"));
curl_setopt(مقبض $, CURLOPT_RETURNTRANSFER, حقيقي);
curl_setopt(مقبض $, CURLOPT_POSTFIELDS, بيانات $);
curl_setopt(مقبض $, CURLOPT_PROXYUSERPWD, $هذا-> proxy_login. ":" . $هذا-> proxy_password);
curl_setopt(مقبض $, CURLOPT_PROXY, $هذا-> proxy_host. ":" . $هذا-> proxy_port);
curl_setopt(مقبض $, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
استجابة $= curl_exec(مقبض $);
إذا (فارغة)
استجابة $)) {
رمي جديد
خطأ("خطأ في الضفيرة:". curly_error(مقبض $), curl_errno(مقبض $));
}
حليقة_إغلاق(مقبض $);
يعود
استجابة $;
}

وظيفة عامة __doRequest(طلب $, الموقع $, $ الإجراء, نسخة $, $one_way= 0 ) {
يعود
$هذا-> callCurl(الموقع $, طلب $);
}

}
?>

يتطلب تجعيدًا ويمكن تمديده، ولكنه يناسب احتياجاتي البسيطة.

إريك دوت كارون في Gmail دوت كوم

الفكر الذي أشار إليه جان في bestbytes، وتمت مناقشته في الخطأ رقم 27777، أحد المصادر الشائعة لـ "تحليل WSDL: تعذر العثور عليه" " حدث خطأ نتيجة محاولة الوصول إلى WSDL المحمي بواسطة مصادقة HTTP. لا يعمل دائمًا تمرير تسجيل الدخول/كلمة المرور في المعلمة الثانية؛ لذا، إذا واجهت رسالة الخطأ هذه وكنت تحاول الوصول إلى ملف WSDL محمي، فحاول تمرير اسم المستخدم وكلمة المرور باستخدام المعلمة الأولى.

مجهول

كان علي أن أواجه سلوكًا غريبًا إلى حد ما عندما حاولت استخدام خدمات الويب Parlay X القياسية دون نجاح. ومع ذلك، وجدت علاجا لمشكلتي.

كانت المشكلة التي واجهتها تتعلق بإرسال طلب مصادقة أساسي HTTP خاطئ وغير صالح إلى خدمة الويب. على الرغم من أنني كنت أرسل بيانات الاعتماد الصحيحة، إلا أنني تلقيت خطأ في المصادقة. اتضح أن PHP كانت ترسل طلبات HTTP إلى نقطة نهاية أخرى لا يتم كشفها مباشرة من خلال خدمة الويب ولا تتطلب نقطة النهاية هذه المصادقة.

كان علاجي لهذه المشكلة هو استخدام هذه السطور البسيطة في مثال استخدام طريقة sendSms Paraly-X.

أولاً، إنشاء عميل صابون بدون أي خيارات مصادقة HTTP:

$client= جديدSoapClient($wsdl_url);
?>

سيقوم الطلب أعلاه بتخزين wsdl في الدليل /tmp. مباشرة بعد هذا البناء، نقوم بإنشاء عميل صابوني آخر، هذه المرة مع خيارات مصادقة HTTP:

يحاول (
$client= جديدSoapClient($wsdl_url، مجموعة مصفوفة("تسجيل الدخول"=> "غريفين",
"كلمة المرور"=> "كلمة المرور"));
) يمسك (
استثناء $e) {
printf("خطأ: إرسال الرسائل: %s\n", -> __إلى سلسلة());
يعود
خطأ شنيع;
}
?>

الآن ينبغي أن تعمل دون أي مشكلة. بدون الاستدعاء الثاني، ستقوم PHP باستدعاء sendSms بدون بيانات الاعتماد مما يؤدي إلى فشل المحاولة بسبب فقدان معلومات المصادقة. لقد وجدت أن هذا الإجراء هو الأبسط.

يجب تنفيذ هذه العملية في كل مرة تنتهي فيها صلاحية wsdl المخزنة مؤقتًا، أو ببساطة يمكن زيادة مدة بقاء wsdl المخزنة مؤقتًا من php.ini

جون دوت جيلبرت في net-entwicklung dot de

لاحظ أن إنشاء عميل صابوني لعنوان URL غير صالح (تختبر ما يحدث عندما لا تكون الخدمة متاحة، أليس كذلك؟) يؤدي عادةً إلى ظهور استثناء يمكن اكتشافه باستخدام حاول..التقاط. ومع ذلك، إذا كان xdebug نشطًا، فسوف تحصل على خطأ فادح، والذي من الواضح أنه لا يمكن اكتشافه.

sloloem في جوجل دوت كوم

واجهت مشكلة أثناء مناقشة استخدام خريطة الفصل والتي استغرقت مني بعض الوقت لحلها. كنت أفترض أن نوع WSDL الذي كانت المستندات تشير إليه هو اسم العنصر الذي تم إرجاعه في SOAP، لذا،

وكنت أتساءل لماذا رسم الخرائط
"classmap"=>صفيف("node"=>"MyNode")

لم يفعل شيئا.
هذا لأنه في WSDL قمت بتعريف العقدة على أنها:

خريطة الفصل التي أحتاجها كانت:
"classmap"=>صفيف("nodeType"=>"MyNode")

تمكنت من العثور على أسماء الأنواع باستخدام SoapClient->__getTypes()
لاحقًا، أدركت أين يمكنني البحث داخل WSDL عن اسم الكتابة الذي أحتاجه.

لا أعلم إذا فاتني شيء واضح بشكل مؤلم ولكن ربما يمكن أن يؤدي هذا إلى توضيح بعض المستندات.

جون

لقد واجهنا بعض المشاكل في استخدام SoapClient للاتصال بخادم خارجي عبر Microsoft ISA (الإصدار 2006 حاليًا ولكن قد ينطبق هذا على الإصدارات الأخرى أيضًا). نحن نوفر proxy_host وproxy_port وproxy_login وproxy_password لكن خادم ISA يُبلغ عن تسجيل الدخول في ملفه الخاص. السجلات كـ "مجهول".

يعتقد مسؤول النظام لدينا أن السبب في ذلك هو أن PHP لا توفر معلومات NTLN (بروتوكول أمان Windows) بالتنسيق الصحيح (وما إذا كان يجب أن تعمل مع الوكلاء الخاصين فهذا بالطبع نقاش آخر). لقد جربنا "اسم المستخدم" و"DOMAIN\اسم المستخدم" دون جدوى. الحل هو إضافة استثناء في خادم ISA لاسم المضيف/IP الهدف؛ يمكن بعد ذلك توفير قيمة فارغة لـ proxy_login وproxy_password ومن المفترض أن يعمل الاتصال بعد ذلك كما هو متوقع.

وفي ملاحظة ذات صلة قليلًا، إذا كنت تواجه مشكلات، فتأكد من توفير رقم المنفذ كعدد صحيح. لن تستخدم بعض إصدارات PHP الوكيل مع SoapClient إذا تم توفير رقم المنفذ كسلسلة.

جان في bestbytes دوت دي

يمكنك الحصول على wsdl، إذا كانت المصادقة الأساسية مطلوبة:

$تسجيل الدخول = "بيرت";
كلمة المرور $= "كلمة مرور بيرت";

$client= جديدSoapClient(
"http://". urlencode($تسجيل الدخول) . ":" . urlencode(كلمة المرور $) . "@www.server.com/path/to/wsdl",
مجموعة مصفوفة(
"تسجيل الدخول"=> $تسجيل الدخول,
"كلمة المرور"=> كلمة المرور $
)
);

?>

المعلومات في نيكسيلفسترو دوت نت

لأي شخص يواجه مشكلة في ArrayOf_xsd_string ويحصل على خطأ مشابه لـ "لم يتم تعريف أداة إلغاء التسلسل لنوع الصفيف (http://www.w3.org/2001/XMLSchema)"
حاول استخدام معلمة "الميزات"، المعينة على SOAP_USE_XSI_ARRAY_TYPE - وهذا يضمن استخدام أداة إلغاء التسلسل الصحيحة.

على سبيل المثال،
$client= جديدSoapClient("بعض.wsdl"، مجموعة مصفوفة("سمات"=> SOAP_USE_XSI_ARRAY_TYPE));
?>

قناص

بحثت عن مثال جيد ولم أجده
أخيرًا وجدته في مكان ما (نسيت أين) أعتقد أن هذا موجود
أفضل مثال لتقديم طلب صابون باستخدام معلمات متعددة

$params->AWSAccessKeyId = AMAZON_API_KEY;
$params->Request->SearchIndex = "الكتب";
$params->Request->Keywords = "php5 oop";

$amazon = new SoapClient("http://webservices.amazon.com
/AWSECommerceService/AWSECommerceService.wsdl");
$result = $amazon->itemSearch($params);

أليكس على reutone فاصلة كوم

لتوصيل PHP SOAP بـ MS SOAP (CRM/EXCHANGE/...) قمت بإنشاء بعض الفئات باستخدام الشرح أدناه وفي أماكن أخرى.
www.reutone.com/heb/articles.php?instance_id=62&actions=show&id=521

naugtur في جوجل دوت كوم

استثناء SoapFault: يبدو أننا لم نحصل على مستند XML لقد تم ذكر حدوث ذلك بالفعل عندما يقوم الخادم الخاص بك بإخراج شيء ما من قبل ... > بطاقة شعار.

ل كل أولئك الذين لديهم مشاكل مع ذلك، ولا يمكن الوصول إلى رمز الخادم:
هذه هي كيفية إنشاء وكيل يقوم بتنظيف الاستجاباتلأنت

بي أتش بي
/**
* فئة بسيطة مأخوذة من مذكرة كتبها جيمس إليس
*/
فصلProxy_ClientيمتدSoapClient{
محمي
$cacheDocument= "" ;
وظيفة عامة
__بناء($wsdl, خيارات $) {
الأبوين:: __بناء($wsdl, خيارات $);
}

/**
* يقوم SetCacheDocument() بتعيين محتويات المستند المخزنة مؤقتًا مسبقًا
*/
وظيفة عامةSetCacheDocument($document) {
$هذا-> cacheDocument= $document;
}

/**
* __doRequest() يتجاوز SoapClient القياسي للتعامل مع الطلب المحلي
*/
وظيفة عامة__doRequest() {
يعود
$هذا-> cacheDocument;
}
}

// ضع هذا الكود في وظيفتك أو في أي مكان قمت بتعيين كافة المتغيرات المطلوبة فيه

$client= جديدSoapClient($wsdl_url, $settings_array);
$باطل= $client-> طريقة $($params); // اتصل بهذا للحصول على استجابة من الخادم

$response_string= $client-> __getLastResponse();

// هذا الجزء يزيل الأشياء
بداية $= com.strpos($response_string, ");
نهاية $= com.strrpos($response_string, ">" );
$response_string= substr($response_string, بداية $, نهاية $- بداية $+ 1 );

// قم بإعداد الوكيل الخاص بك
$proxy= جديدProxy_Client($wsdl_url, $settings_array);
// واملأها باستجابة الخادم
$proxy-> SetCacheDocument($response_string);

$and_finally_the_result_is= $proxy-> طريقة $($params);

print_r($and_finally_the_result_is); // هذا يسمح لك برؤية ما هو موجود هناك

?>

$method هو اسم الطريقة، على سبيل المثال $method="getVersion";
$params - معلمات نموذجية لطريقة الصابون

نصائح للمستخدمين:

    إذا كنت تعرف ملف WSDL، فيمكنك إعداد رابط سريع لنماذج العميل باستخدام
    http://www.?template=/clientform.html&fn=soapform
    &SoapTemplate=none&SoapWSDL=Your_WSDL_File
    أو
    http://www..html?SoapWSDL=Your_WSDL_File

    يقوم الخادم بتخزين ملفات WSDL مؤقتًا في العمليات العادية لتحسين الأداء. إذا قمت بإجراء أية تغييرات على ملف WSDL، فحدد لاخانة الاختيار.

نصائح للمطورين:

    يستخدم<توثيق> كلما أمكن ذلك في ملف WSDL الخاص بك لتوفير التعليمات. سيتم عرضه في نموذج العميل.

    استخدم نوع التعداد إذا كان العنصر يحتوي على عدد ثابت من القيم. سيتم عرضها كمربعات منسدلة.

دلائل الميزات:

    دعم كل من مخطط XML لعامي 1999 و2001. تستخدم الأداة المخطط المحدد في ملف WSDL لإنشاء طلبات SOAP.

    دعم مجموعة ومجموعة من الهياكل. يتم دعم المصفوفات ذات البعد الواحد فقط. عذرًا، لا توجد صفائف متفرقة.

    قادر على إجراء تسلسل لأنواع البيانات المعقدة ومجموعة من أنواع البيانات المعقدة، حتى الهياكل المضمنة متعددة المستويات.

    التعامل مع المعرف/HREF في كل من رسائل SOAP وتعريفات المخطط.

    دعم كل من قسم SOAP 5/7 وترميزات المستندات/الحرفية.

تفاصيل تقنية- الربط الديناميكي لخدمات SOAP

الربط هو عقد بين منطق العميل ومنطق الخادم. يوجد نوعان من الارتباطات في SOAP: ربط الكائنات (أو ربط SOAP) وربط المعلمات. تقوم معظم مجموعات أدوات SOAP بربط الكائنات الثابتة عن طريق إنشاء كائنات وكيل من جانب العميل. تكمن المشكلة في أنه، على عكس وحدة البرمجة التقليدية حيث تكون الكائنات/الواجهات مستقرة، فإن خدمات الويب عرضة للتغيير في أي لحظة دون سابق إنذار، لأنها غالبًا ما تكون مملوكة/مسيطر عليها من قبل طرف ثالث. وتحدث مشكلة أخرى عندما يزداد عدد خدمات الويب التي يمكن الوصول إليها، وقد يصبح كود المصدر الذي تم إنشاؤه بمثابة كابوس للصيانة بسرعة. أخيرًا، عندما تكون خدمات الويب التي سيتم الوصول إليها غير معروفة، وهو أمر مرجح في كثير من الأحيان، يصبح الربط المبكر مستحيلاً، أو على الأقل صعبًا. يعد إنشاء كائن وكيل لخدمة سيتم بناؤها في المستقبل مشروعًا بحثيًا مثيرًا للاهتمام.

يوضح عميل SOAP العام الارتباطات الديناميكية (أو روابط وقت التشغيل) لخدمات ومعلمات SOAP. يتم إنشاء كائن في وقت التنفيذ عندما يتم تحديد ملف WSDL، وترتبط قيم المعلمات برسالة SOAP قبل التسليم مباشرة. يمكن أن تؤدي تقنية الربط المتأخر (أو الربط المتأخر) إلى تقليل تكلفة الصيانة بشكل كبير، لأنه يمكن استخدام عميل واحد للوصول إلى العديد من خدمات الويب.

خطأ:المحتوى محمي!!