SOAP چیست؟ مقدمه ای بر XML-Schema

سلام به همه!
این اتفاق افتاد که اخیراً شروع به توسعه خدمات وب کردم. اما امروز موضوع در مورد من نیست، بلکه در مورد این است که چگونه می توانیم وب سرویس XML خود را بر اساس پروتکل SOAP 1.2 بنویسیم.

امیدوارم پس از مطالعه موضوع بتوانید:

  • پیاده سازی سرور خود را از یک برنامه وب بنویسید.
  • پیاده سازی مشتری خود را از یک برنامه وب بنویسید.
  • شرح خدمات وب خود را بنویسید (WSDL).
  • آرایه های مشتری از همان نوع داده را به سرور ارسال کنید.

همانطور که حدس زده اید، همه جادوها با استفاده از PHP و کلاس های داخلی SoapClient و SoapServer انجام می شود. خرگوش ما سرویسی برای ارسال پیامک خواهد بود.

1 بیان مشکل

1.1 مرزها

در ابتدا پیشنهاد می کنم به نتیجه ای بپردازیم که در پایان مبحث به دست خواهیم آورد. همانطور که در بالا اعلام شد سرویسی برای ارسال پیامک می نویسیم و به طور دقیق تر از منابع مختلف از طریق پروتکل SOAP پیام دریافت می کنیم. پس از آن، ما در نظر خواهیم گرفت که آنها به چه شکلی به سرور می رسند. متأسفانه فرآیند صف بندی پیام ها برای تحویل بیشتر به ارائه دهنده به دلایل زیادی از حوصله این پست خارج است.

1.2 چه داده هایی را تغییر خواهیم داد؟

عالی است، ما در مورد مرزها تصمیم گرفته ایم! قدم بعدی که باید برداشته شود این است که تصمیم بگیریم چه داده هایی را بین سرور و کلاینت مبادله کنیم. در مورد این موضوع، من پیشنهاد می کنم موها را برای مدت طولانی از هم جدا نکنید و بلافاصله به سوالات اصلی خود پاسخ دهید:

  • برای ارسال پیامک به مشترک چه حداقل داده هایی باید به سرور ارسال شود؟
  • چه حداقل داده هایی باید از سرور ارسال شود تا نیازهای مشتری را برآورده کند؟

چیزی به من می گوید که برای این باید موارد زیر را ارسال کنید:

  • شماره تلفن همراه و
  • متن پیامک

در اصل، این دو ویژگی برای ارسال کافی است، اما من بلافاصله تصور می کنم که یک اس ام اس با تبریک تولد ساعت 3 یا 4 صبح برای شما می آید! در این لحظه از همه ممنونم که مرا فراموش نکردند! بنابراین ما نیز به سرور و ارسال خواهیم کرد

  • تاریخ ارسال پیامک

مورد بعدی که می خواهم به سرور ارسال کنم این است:

  • نوع پیام

این پارامتر اجباری نیست، اما اگر سریعاً نیاز داشته باشیم به رئیس بگوییم که چه تعداد از مشتریان خود را از اخبار خود "خوشحال" کرده‌ایم و همچنین آمارهای زیبایی در این مورد ترسیم کنیم، می‌تواند برای ما بسیار مفید باشد.

و با این حال، من چیزی را فراموش کردم! اگر کمی بیشتر تأمل کنیم، شایان ذکر است که مشتری می تواند یک پیام کوتاه یا تعدادی از آنها را در یک زمان به سرور ارسال کند. به عبارت دیگر، یک بسته داده می تواند حاوی پیام هایی از یک تا بی نهایت باشد.

در نتیجه، دریافتیم که برای ارسال یک پیام کوتاه به داده های زیر نیاز داریم:

  • شماره موبایل،
  • متن پیامک،
  • زمان ارسال پیامک به مشترک،
  • نوع پیام

ما به سوال اول پاسخ دادیم، حالا باید به سوال دوم پاسخ دهیم. و شاید به خودم این اجازه را بدهم که کمی به هم بریزم. بنابراین، از سرور فقط داده های Boolean را ارسال می کنیم که معنای آن به این معنی است:

  • درست - بسته با موفقیت به سرور رسید، احراز هویت را پشت سر گذاشت و برای ارسال به ارائه دهنده پیام کوتاه در صف قرار گرفت.
  • نادرست - در همه موارد دیگر

این توضیح بیان مشکل را به پایان می رساند! و در نهایت، بیایید به قسمت سرگرم کننده آن بپردازیم - بیایید بفهمیم این صابون چه نوع جانور عجیبی است!

2 SOAP چیست؟

به طور کلی، در ابتدا قصد نداشتم چیزی در مورد SOAP بنویسم و ​​می خواستم خودم را به پیوندهایی به وب سایت w3.org با مشخصات لازم و همچنین پیوندهایی به ویکی پدیا محدود کنم. اما در نهایت تصمیم گرفتم یک یادداشت کوتاه در مورد این پروتکل بنویسم.

و من داستان خود را با این واقعیت آغاز می کنم که این پروتکل تبادل داده متعلق به زیر مجموعه ای از پروتکل های مبتنی بر پارادایم به اصطلاح RPC (Remote Procedure Call) است که پاد پاد آن REST (انتقال حالت نمایندگی) است. شما می توانید در مورد این موضوع در ویکی پدیا بیشتر بخوانید؛ پیوندهای مقالات در انتهای موضوع قرار دارند. از این مقالات، ما باید موارد زیر را درک کنیم: «رویکرد RPC امکان استفاده از تعداد کمی از منابع شبکه با تعداد زیادی روش و یک پروتکل پیچیده را می‌دهد. با رویکرد REST، تعداد روش‌ها و پیچیدگی پروتکل کاملاً محدود است، به این معنی که تعداد منابع فردی می‌تواند زیاد باشد. یعنی در رابطه با ما، این بدان معناست که در سایت در مورد رویکرد RPC همیشه یک ورودی (پیوند) به سرویس وجود خواهد داشت و چه رویه‌ای برای پردازش داده‌های ورودی که همراه با داده‌ها ارسال می‌کنیم فراخوانی شود، در حالی که با رویکرد REST در سایت ما ورودی‌ها (پیوندها) زیادی دارد که هر کدام فقط داده‌های خاصی را می‌پذیرند و پردازش می‌کنند. اگر کسی که مطالعه می کند می داند چگونه تفاوت این رویکردها را حتی ساده تر توضیح دهد، حتماً در نظرات بنویسد!

نکته بعدی که باید در مورد SOAP بدانیم این است که این پروتکل از همان XML به عنوان یک انتقال استفاده می کند که از یک طرف بسیار خوب است، زیرا زرادخانه ما بلافاصله شامل قدرت کامل مجموعه ای از فناوری های مبتنی بر این زبان نشانه گذاری است، یعنی XML-Schema - زبانی برای توصیف ساختار یک سند XML (با تشکر از ویکی پدیا!)، که امکان تأیید خودکار داده های دریافت شده توسط سرور را فراهم می کند. از مشتریان

و بنابراین، اکنون می دانیم که SOAP یک پروتکل است که برای اجرای فراخوانی های رویه از راه دور استفاده می شود و از XML به عنوان یک انتقال استفاده می کند! اگر مقاله ویکی‌پدیا را بخوانید، می‌توانید از آنجا نیز یاد بگیرید که می‌توان از آن بر روی هر پروتکل در سطح برنامه استفاده کرد، و نه فقط در ترکیب با HTTP (متاسفانه، در این مبحث فقط SOAP را در مقابل HTTP در نظر خواهیم گرفت). و می دانید چه چیزی را در این همه بیشتر دوست دارم؟ اگر هیچ حدس و گمانی وجود ندارد، پس من یک اشاره می کنم - SOAP!... هنوز هم حدس نمی زنم؟... آیا مطمئن هستید که مقاله را در ویکی پدیا می خوانید؟... به طور کلی، من شما را بیشتر شکنجه نخواهم کرد. بنابراین، من مستقیماً به پاسخ می‌روم: "SOAP (از پروتکل دسترسی به شیء ساده انگلیسی - ساده پروتکلدسترسی به اشیاء؛ تا مشخصات 1.2)". قابل توجه ترین نکته در مورد این خط به صورت ایتالیک است! من نمی دانم شما از همه اینها چه نتیجه ای گرفتید ، اما موارد زیر را می بینم - از آنجایی که این پروتکل به هیچ وجه نمی تواند "ساده" نامیده شود (و ظاهراً حتی w3 نیز با این موافق است) ، پس از نسخه 1.2 به نوعی رمزگشایی متوقف شد ! و به عنوان SOAP، just SOAP، نقطه شناخته شد.

خب، باشه، ببخشید، کمی آن را کنار گذاشتیم. همانطور که قبلاً نوشتم، XML به عنوان انتقال استفاده می شود و بسته هایی که بین مشتری و سرور حرکت می کنند، پاکت SOAP نامیده می شوند. اگر ساختار کلی پاکت نامه را در نظر بگیرید، برایتان بسیار آشنا به نظر می رسد، زیرا... شبیه نشانه گذاری یک صفحه HTML است. یک بخش اصلی دارد - پاکت کن، که شامل بخش هایی است سرتیترو بدن، یا عیب. که در بدنداده ها منتقل می شود و یک بخش اجباری از پاکت است، در حالی که سرتیتراختیاری است که در سرتیترمجوز یا هر داده دیگری که مستقیماً با داده های ورودی رویه های وب سرویس مرتبط نیست ممکن است منتقل شود. در باره عیبچیز خاصی برای گفتن وجود ندارد، به جز اینکه در صورت بروز هر گونه خطایی از سرور به مشتری می رسد.

اینجاست که داستان بررسی من در مورد پروتکل SOAP به پایان می رسد (زمانی که کلاینت و سرور ما در نهایت یاد بگیرند که آنها را روی یکدیگر اجرا کنند ما به خود پاکت ها و ساختار آنها با جزئیات بیشتری نگاه خواهیم کرد) و یک مورد جدید شروع می شود - در مورد همراه SOAP به نام WSDL(زبان شرح خدمات وب). بله، بله، این همان چیزی است که بسیاری از ما را حتی از تلاش برای پیاده سازی API خود در این پروتکل می ترساند. در نتیجه، ما معمولا چرخ خود را با JSON به عنوان حمل و نقل دوباره اختراع می کنیم. پس WSDL چیست؟ WSDL زبانی برای توصیف خدمات وب و دسترسی به آنها بر اساس زبان XML (c) ویکی پدیا است. اگر این تعریف تمام معنای مقدس این فناوری را برای شما روشن نمی کند، من سعی می کنم آن را به زبان خودم توصیف کنم!

WSDL طوری طراحی شده است که به مشتریان ما اجازه می دهد تا به طور معمول با سرور ارتباط برقرار کنند. برای انجام این کار، فایل با پسوند "*.wsdl" اطلاعات زیر را شرح می دهد:

  • چه فضاهای نامی استفاده شد؟
  • چه طرحواره های داده ای استفاده شد؟
  • وب سرویس چه نوع پیام هایی را از مشتریان انتظار دارد؟
  • کدام داده متعلق به کدام رویه خدمات وب است،
  • وب سرویس شامل چه رویه هایی است؟
  • چگونه مشتری باید رویه های وب سرویس را فراخوانی کند،
  • تماس های مشتریان باید به کدام آدرس ارسال شود؟

همانطور که می بینید، این فایل کل وب سرویس است. با مشخص کردن آدرس فایل WSDL در کلاینت، همه چیز را در مورد هر وب سرویسی خواهیم دانست! در نتیجه، نیازی نیست که مطلقاً چیزی در مورد محل قرارگیری خود وب سرویس بدانیم. تنها چیزی که باید بدانید محل فایل WSDL آن است! به زودی متوجه خواهیم شد که صابون به اندازه ضرب المثل های روسی ترسناک نیست.

3 مقدمه ای بر XML-Schema

اکنون ما چیزهای زیادی در مورد چیستی SOAP، آنچه در داخل آن وجود دارد، می دانیم و مروری داریم بر پشته فناوری که آن را احاطه کرده است. از آنجایی که اول از همه، SOAP یک روش تعامل بین یک کلاینت و یک سرور است و زبان نشانه گذاری XML به عنوان یک انتقال برای آن استفاده می شود، در این بخش کمی در مورد چگونگی اعتبارسنجی خودکار داده ها با استفاده از طرحواره های XML خواهیم فهمید.

وظیفه اصلی نمودار توصیف ساختار داده هایی است که قرار است پردازش کنیم. تمام داده ها در طرحواره های XML به دو دسته تقسیم می شوند ساده(اسکالر) و مجتمع(ساختارها) انواع. انواع ساده شامل انواع زیر است:

  • خط،
  • عدد،
  • مقدار بولی،
  • تاریخ.

چیزی بسیار ساده که هیچ پسوندی در داخل آن وجود ندارد. آنتی پاد آنها از انواع پیچیده پیچیده است. ساده ترین نمونه از انواع پیچیده که به ذهن همه می رسد، اشیا هستند. مثلا یک کتاب. این کتاب شامل خواص: نویسنده, نام, قیمت, شماره شابکو غیره. و این ویژگی ها به نوبه خود می توانند انواع ساده یا پیچیده باشند. و وظیفه طرحواره XML توصیف این است.

پیشنهاد می کنم راه دوری نرویم و برای پیامکمان یک طرح XML بنویسیم! در زیر توضیحات xml پیامک آمده است:

71239876543 پیام آزمایشی 2013-07-20T12:00:00 12

نمودار نوع پیچیده ما به صورت زیر خواهد بود:

این ورودی به شرح زیر است: ما یک متغیر داریم " پیام"نوع" پیام"و یک نوع پیچیده وجود دارد به نام " پیام"، که از مجموعه ای متوالی از عناصر تشکیل شده است" تلفن"تایپ کنید رشته, « متن"تایپ کنید رشته, « تاریخ"تایپ کنید زمان قرار, « نوع"تایپ کنید اعشاری. این انواع ساده هستند و قبلاً در توضیحات طرحواره تعریف شده اند. تبریک می گویم! ما اولین طرح XML خود را نوشتیم!

من فکر می کنم که معنای عناصر " عنصر"و" نوع پیچیده"همه چیز کم و بیش برای شما روشن شده است، بنابراین ما دیگر روی آنها تمرکز نمی کنیم و بیایید مستقیماً به عنصر آهنگساز برویم." توالی" وقتی از عنصر آهنگساز استفاده می کنیم " توالی"به شما اطلاع می دهیم که عناصر موجود در آن باید همیشه به ترتیب مشخص شده در نمودار قرار داشته باشند و همه آنها اجباری هستند. اما ناامید نشو! دو عنصر آهنگساز دیگر در طرحواره های XML وجود دارد: انتخاب"و" همه" آهنگساز" انتخاب"اعلام می کند که باید یکی از عناصر ذکر شده در آن وجود داشته باشد و آهنگساز" همه» – هر ترکیبی از عناصر فهرست شده.

همانطور که به یاد دارید، در بخش اول موضوع توافق کردیم که از یک تا بی نهایت پیامک ها را می توان در یک بسته منتقل کرد. بنابراین، من پیشنهاد می کنم درک کنیم که چگونه چنین داده هایی در طرح XML اعلام می شوند. ساختار کلی بسته ممکن است به شکل زیر باشد:

71239876543 پیام آزمایشی 1 2013-07-20T12:00:00 12 71239876543 پیام آزمایشی N 2013-07-20T12:00:00 12

نمودار چنین نوع پیچیده ای به صورت زیر است:

بلوک اول حاوی اعلان آشنا از نوع پیچیده است. پیام" اگر متوجه شدید، پس در هر نوع ساده موجود در " پیام"، ویژگی های شفاف کننده جدید اضافه شده است" کوچک اتفاق می افتد"و" حداکثر اتفاق می افتد" همانطور که ممکن است از نام آن حدس بزنید، اولین ( کوچک اتفاق می افتد) نشان می دهد که این دنباله باید حداقل دارای یک عنصر از نوع " باشد. تلفن», « متن», « تاریخ"و" نوع"، در حالی که بعدی ( حداکثر اتفاق می افتد) ویژگی به ما اعلام می کند که حداکثر یک عنصر از این قبیل در دنباله ما وجود دارد. در نتیجه، زمانی که ما طرحواره های خود را برای هر داده ای می نویسیم، وسیع ترین انتخاب در مورد نحوه پیکربندی آنها به ما داده می شود!

بلوک دوم نمودار عنصر " را اعلام می کند لیست پیام ها"نوع" MessageList" واضح است که " MessageList"یک نوع پیچیده است که شامل حداقل یک عنصر است" پیام"، اما حداکثر تعداد چنین عناصری محدود نیست!

4 WSDL خود را بنویسید

آیا به یاد دارید که WSDL سرویس وب ما است؟ امیدوارم یادت بیاد! همانطور که ما آن را می نویسیم، وب سرویس کوچک ما روی آن اجرا می شود. بنابراین، من پیشنهاد می کنم که در اطراف خود قاطی نکنید.

به طور کلی، برای اینکه همه چیز برای ما درست کار کند، باید یک فایل WSDL با نوع MIME صحیح را به مشتری منتقل کنیم. برای انجام این کار، باید وب سرور خود را بر این اساس پیکربندی کنید، یعنی نوع MIME را برای فایل هایی با پسوند "*.wsdl" روی خط زیر تنظیم کنید:

برنامه/wsdl+xml

اما در عمل، من معمولا هدر HTTP را از طریق PHP ارسال می کنم. متن/xml»:

Header("Content-Type: text/xml; charset=utf-8");

و همه چیز عالی کار کرد!

می خواهم فوراً به شما هشدار دهم که وب سرویس ساده ما توضیحات نسبتاً چشمگیری خواهد داشت ، بنابراین نگران نباشید ، زیرا ... بیشتر متن آب اجباری است و با یک بار نوشتن می توانید مدام آن را از یک وب سرویس به سرویس دیگر کپی کنید!

از آنجایی که WSDL XML است، باید مستقیماً در خط اول در مورد آن بنویسید. عنصر ریشه فایل همیشه باید نامیده شود تعاریف»:

به طور معمول، WSDL از 4-5 بلوک اصلی تشکیل شده است. اولین بلوک، تعریف وب سرویس یا به عبارت دیگر نقطه ورود است.

اینجا می گوید که ما یک سرویس داریم به نام - " SmsService" در اصل، تمام نام های موجود در فایل WSDL می تواند توسط شما به هر چیزی که می خواهید تغییر کند، زیرا آنها مطلقاً هیچ نقشی ندارند.

پس از این ما اعلام می کنیم که در وب سرویس ما " SmsServiceیک نقطه ورود ("پورت") به نام " وجود دارد SmsServicePort" به این نقطه ورود است که تمام درخواست های مشتریان به سرور ارسال می شود. و در عنصر " نشانی» پیوند به فایل کنترل کننده ای که درخواست ها را می پذیرد.

هنگامی که وب سرویس را تعریف کردیم و نقطه ورود را برای آن مشخص کردیم، باید رویه های پشتیبانی شده را به آن متصل کنیم:

برای انجام این کار، لیستی از عملیات و به چه شکلی که آنها را فراخوانی می‌کند، ارائه می‌کند. آن ها برای بندر " SmsServicePort"یک الزام آور تحت نام تعریف شده است" SMSServiceBinding"، که یک نوع تماس دارد" rpcو HTTP به عنوان پروتکل انتقال استفاده می شود. بنابراین، ما در اینجا نشان دادیم که یک تماس RPC از طریق HTTP برقرار خواهیم کرد. پس از این ما توضیح می دهیم که کدام رویه ها ( عمل) در وب سرویس پشتیبانی می شوند. ما فقط از یک روش پشتیبانی خواهیم کرد - " ارسال پیامک" از طریق این روش پیام های فوق العاده ما به سرور ارسال می شود! پس از اعلام رویه، باید مشخص شود که داده ها به چه شکلی منتقل می شوند. در این مورد، نشان داده شده است که از پاکت های استاندارد SOAP استفاده خواهد شد.

پس از آن، باید رویه را به پیام‌ها متصل کنیم:

برای این کار مشخص می کنیم که binding ما از نوع " SMSServicePortType"و در عنصر" portType"با نامی از همان نوع، ما اتصال رویه ها به پیام ها را نشان می دهیم. و بنابراین، پیام دریافتی (از مشتری به سرور) نامیده می شود sendSmsRequest"، و خروجی (از سرور به مشتری)" sendSmsResponse" مانند همه نام‌ها در WSDL، نام پیام‌های ورودی و خروجی دلخواه است.

حال باید خود پیام ها را شرح دهیم، یعنی. ورودی و خروجی:

برای این کار ما عناصر را اضافه می کنیم " پیام"با اسامی" sendSmsRequest"و" sendSmsResponse" به ترتیب. در آنها نشان می دهیم که ورودی باید یک پاکت باشد که ساختار آن با نوع داده مطابقت دارد. درخواست" پس از آن یک پاکت نامه از سرور حاوی نوع داده بازگردانده می شود - " واکنش».

اکنون باید کمی انجام دهیم - شرحی از این انواع را به فایل WSDL خود اضافه کنیم! و به نظر شما WSDL داده های ورودی و خروجی را چگونه توصیف می کند؟ فکر می‌کنم مدت‌ها پیش همه چیز را فهمیده‌اید و به خود گفته‌اید که با استفاده از طرحواره‌های XML! و شما کاملا درست خواهید بود!

می توانید به ما تبریک بگویید! اولین WSDL ما نوشته شده است! و ما یک قدم به رسیدن به هدفمان نزدیکتر شده ایم.
در مرحله بعد، به آنچه PHP برای توسعه برنامه های کاربردی توزیع شده خودمان در اختیار ما قرار می دهد، خواهیم دید.

5 اولین سرور SOAP ما

قبلاً نوشتم که برای ایجاد یک سرور SOAP در PHP از کلاس SoapServer داخلی استفاده خواهیم کرد. برای اینکه تمام اقدامات بعدی مانند من اتفاق بیفتد، باید PHP خود را کمی تغییر دهید. برای دقیق تر بودن، باید مطمئن شوید که پسوند php-soap را نصب کرده اید. بهتر است نحوه نصب آن را روی وب سرور خود در وب سایت رسمی PHP بخوانید (لیست مراجع را ببینید).

بعد از اینکه همه چیز نصب و پیکربندی شد، باید یک فایل در پوشه اصلی هاست شما ایجاد کنیم. smsservice.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 را نوشتیم، سه موجودیت را برای پاکت ورودی به سرور توصیف کرد: درخواست, MessageListو پیام. بر این اساس کلاس ها درخواست, MessageListو پیامبازتابی از این موجودات در اسکریپت PHP ما هستند.

زمانی که اشیاء را تعریف کردیم، باید یک شی بسازیم ( $req) که به سرور ارسال می کنیم. پس از آن دو خط محبوب ترین برای ما می آیند! مشتری SOAP ما! باور کنید یا نه، این برای سرور ما برای شروع دریافت پیام از مشتری و همچنین برای سرور ما برای دریافت و پردازش موفقیت آمیز آنها کافی است! در اولین مورد، یک نمونه از کلاس SoapClient ایجاد می کنیم و آدرس محل فایل WSDL را به سازنده آن ارسال می کنیم و در پارامترها به صراحت نشان می دهیم که با استفاده از پروتکل SOAP نسخه 1.2 کار خواهیم کرد. در خط بعدی متد را فراخوانی می کنیم ارسال پیامکهدف - شی مشتری $و بلافاصله نتیجه را در مرورگر نمایش دهید.
بیایید آن را اجرا کنیم و ببینیم در نهایت چه چیزی به دست آوردیم!

شی زیر از سرور به من برگردانده شد:

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

و این عالی است، زیرا ... اکنون ما با اطمینان می دانیم که سرور ما کار می کند و نه تنها کار می کند، بلکه می تواند مقادیری را به مشتری برگرداند!

حالا بیایید به گزارشی که با احتیاط در سمت سرور نگه می داریم نگاه کنیم! در قسمت اول آن، داده های خامی را می بینیم که به سرور رسیده است:

79871234567 پیام آزمایشی 1 2013-07-21T15:00:00.26 15

این پاکت است. حالا شما می دانید که چگونه به نظر می رسد! اما بعید است که ما علاقه مند باشیم که همیشه به آن نگاه کنیم، بنابراین بیایید شی را از فایل log از سریال خارج کنیم و ببینیم آیا همه چیز خوب است یا خیر:

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)

همانطور که می بینید، شی به درستی deserialized شد، که می خواهم به همه ما تبریک بگویم! چیز جالب تری در آینده در انتظار ما است! یعنی کلاینت را نه فقط یک پیام کوتاه بلکه یک بسته کامل (به عبارت دقیق تر، سه) به سرور ارسال می کنیم!

7 ارسال اشیاء پیچیده

بیایید به این فکر کنیم که چگونه می توانیم یک دسته کامل از پیام ها را در یک بسته به سرور منتقل کنیم؟ احتمالاً ساده ترین راه، سازماندهی یک آرایه در داخل عنصر messageList خواهد بود! بیا انجامش بدیم:

// ایجاد یک شی برای ارسال به سرور $req = new Request(); $req->messageList = new MessageList(); $msg1 = new Message(); $msg1->phone = "79871234567"; $msg1->text = "پیام آزمایشی 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = new Message(); $msg2->phone = "79871234567"; $msg2->text = "پیام آزمایشی 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = new Message(); $msg3->phone = "79871234567"; $msg3->text = "پیام آزمایشی 3"; $msg3->date = "2014-08-22T16: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

چه مزخرفی، شما می گویید؟ و به نوعی حق با شماست، زیرا... به محض اینکه متوجه شدیم یک شی از کلاینت خارج شده است، کاملاً به همان شکل در قالب یک پاکت به سرور ما آمد. درست است، پیام های اس ام اس در XML آن طور که ما نیاز داشتیم سریال سازی نمی شدند - آنها باید در عناصر پیچیده می شدند. پیام، نه در ساختار. حال بیایید ببینیم که چنین شیئی به چه شکلی به روش می آید ارسال پیامک:

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 " => string "79871234567" (length=11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length= 19) عمومی "type" => رشته "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

وارد روش شد ارسال پیامکشی دارای ساختار زیر است:

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 " => string "79871234567" (length=11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length= 19) عمومی "type" => رشته "17" (طول = 2)

در مورد من، "مجموع از تغییر مکان اصطلاحات تغییر نمی کند" (ج). چی جعلی، چی ساختار- ما هنوز به هدف خود نرسیدیم! و برای رسیدن به آن، باید مطمئن شویم که به جای این نام های نامفهوم، نام اصلی ما نمایش داده شود. پیام. اما نویسنده هنوز نمی داند چگونه به این امر دست یابد. بنابراین، تنها کاری که می توانیم انجام دهیم این است که از شر ظرف اضافی خلاص شویم. به عبارت دیگر، ما اکنون مطمئن خواهیم شد که به جای پیامتبدیل شد جعلی! برای انجام این کار، شی را به صورت زیر تغییر دهید:

// ایجاد یک شی برای ارسال به سرور $req = new Request(); $msg1 = new Message(); $msg1->phone = "79871234567"; $msg1->text = "پیام آزمایشی 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = new Message(); $msg2->phone = "79871234567"; $msg2->text = "پیام آزمایشی 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = new Message(); $msg3->phone = "79871234567"; $msg3->text = "پیام آزمایشی 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;

اگر خوش شانس باشیم و نام صحیح از نمودار بیرون بیاید چه؟ برای انجام این کار، بیایید به پاکت ارسال شده نگاه کنیم:

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

بله، معجزه ای اتفاق نیفتاد! جعلی- ما برنده نخواهیم شد! بیا به ارسال پیامکشی در این مورد به شکل زیر خواهد بود:

Object(stdClass) public "messageList" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public " text" => رشته "پیام آزمایشی 1" (طول = 37) عمومی "تاریخ" => رشته "2013-07-21T15:00:00.26" (طول=22) عمومی "نوع" => رشته "15" (طول =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" (طول = 19) عمومی "type" => رشته "16" (طول=2) 2 => شی (stdClass) عمومی "phone" => رشته "79871234567" (طول= 11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string " 17 اینچ (طول = 2)

همانطور که می گویند - "تقریبا"! در این یادداشت (کمی غم انگیز)، من پیشنهاد می کنم به آرامی همه چیز را جمع بندی کنیم و برای خودمان نتیجه گیری کنیم.

8 نتیجه گیری

بالاخره به اینجا رسیدیم! بیایید بفهمیم که اکنون چه کاری می توانید انجام دهید:

  • می توانید فایل WSDL لازم برای وب سرویس خود را بنویسید.
  • شما به راحتی می توانید مشتری خود را بنویسید که می تواند از طریق SOAP با سرور ارتباط برقرار کند.
  • شما می توانید سرور خود را بنویسید که از طریق SOAP با دنیای خارج ارتباط برقرار می کند.
  • شما می توانید آرایه هایی از همان نوع اشیاء را از مشتری خود به سرور ارسال کنید (با برخی محدودیت ها).

ما همچنین در طول تحقیقات کوچک خود به برخی از اکتشافات دست یافتیم:

  • کلاس SoapClient بومی ساختارهای داده ای از همان نوع را در XML به درستی سریال نمی کند.
  • هنگام سریال سازی یک آرایه به XML یک عنصر اضافی به نام ایجاد می کند ساختار;
  • هنگام سریال سازی یک شی در XML یک عنصر اضافی به نام ایجاد می کند جعلی;
  • جعلیبدتر از ساختاربا توجه به این واقعیت که پاکت نامه فشرده تر است (فضاهای نام اضافی به هدر XML پاکت اضافه نمی شود).
  • متأسفانه، کلاس SoapServer به طور خودکار داده های پاکت را با طرح XML ما تأیید نمی کند (شاید سرورهای دیگر نیز این کار را انجام نمی دهند).

بخش غزلی.

تصور کنید که سیستم خاصی را پیاده سازی کرده اید یا در حال پیاده سازی هستید که باید از بیرون قابل دسترسی باشد. آن ها سرور خاصی وجود دارد که باید با آن ارتباط برقرار کنید. به عنوان مثال یک وب سرور.

این سرور می تواند اقدامات زیادی را انجام دهد، با پایگاه داده کار کند، برخی از درخواست های شخص ثالث را به سرورهای دیگر انجام دهد، محاسباتی را انجام دهد و غیره. طبق سناریویی که او شناخته شده است (یعنی بر اساس سناریوی توسعه دهندگان) زندگی کند و احتمالاً توسعه یابد. ارتباط شخصی با چنین سروری جالب نیست، زیرا ممکن است نتواند/نخواهد صفحات زیبایی با تصاویر و سایر محتوای کاربرپسند ارائه دهد. نوشته شده است و کار می کند تا زمانی که از آن خواسته می شود کار کند و داده ارائه کند، بدون نگرانی از خوانایی آن توسط انسان، مشتری خودش با آن برخورد می کند.

سایر سیستم‌ها با دسترسی به این سرور، می‌توانند داده‌های دریافتی از این سرور را به صلاحدید خود دفع کنند - پردازش، جمع‌آوری، ارسال به مشتریان خود و غیره.

خوب یکی از گزینه های ارتباط با چنین سرورهایی SOAP است. پروتکل تبادل پیام SOAP xml.

بخش عملی

یک وب سرویس (این نام چیزی است که سرور ارائه می دهد و مشتریان از آن استفاده می کنند) امکان برقراری ارتباط با سرور را با پیام هایی با ساختار واضح فراهم می کند. واقعیت این است که وب سرویس هیچ داده ای را نمی پذیرد. وب سرویس به هر پیامی که با قوانین مطابقت نداشته باشد با خطا پاسخ می دهد. ضمناً خطا به شکل xml با ساختار واضح نیز خواهد بود (که در مورد متن پیام صادق نیست).

WSDL (زبان شرح خدمات وب). قوانینی که بر اساس آن پیام ها برای وب سرویس ایجاد می شوند نیز با استفاده از xml توضیح داده شده اند و همچنین ساختار واضحی دارند. آن ها اگر یک وب سرویس توانایی فراخوانی یک متد را فراهم می کند، باید به مشتریان اجازه دهد تا بدانند چه پارامترهایی برای این روش استفاده می شود. اگر وب سرویس یک رشته برای Method1 به عنوان پارامتر انتظار داشته باشد و رشته باید Param1 نامیده شود، این قوانین در توضیحات وب سرویس مشخص می شوند.

نه تنها انواع ساده، بلکه اشیا و مجموعه ای از اشیاء نیز می توانند به عنوان پارامتر ارسال شوند. توصیف یک شی به شرح هر جزء از شی خلاصه می شود. اگر یک شی از چندین فیلد تشکیل شده باشد، هر فیلد، نوع، نام آن (مقادیر ممکن چیست) توضیح داده می شود. فیلدها همچنین می توانند از نوع پیچیده باشند و به همین ترتیب تا زمانی که شرح انواع به موارد ساده ختم شود - رشته، بولی، عدد، تاریخ... با این حال، برخی از انواع خاص ممکن است ساده باشند، مهم است که مشتریان می توانند بفهمند که چه ارزش هایی ممکن است حاوی باشند.

برای مشتریان کافی است آدرس وب سرویس را بدانند؛ wsdl همیشه در نزدیکی شما خواهد بود که از طریق آن می توانید از روش ها و پارامترهای آنها که این وب سرویس ارائه می دهد ایده بگیرید.

مزایای این همه زنگ و سوت چیست:

  • در اکثر سیستم ها، شرح روش ها و انواع به طور خودکار اتفاق می افتد. آن ها برنامه نویس روی سرور فقط باید بگوید که این روش را می توان از طریق وب سرویس فراخوانی کرد و توضیحات wsdl به طور خودکار تولید می شود.
  • توضیحاتی که ساختار واضحی دارد برای هر مشتری صابونی قابل خواندن است. آن ها سرویس وب هر چه باشد، مشتری متوجه خواهد شد که وب سرویس چه داده هایی را دریافت می کند. با استفاده از این توضیحات، کلاینت می تواند ساختار داخلی خود را از کلاس های شی بسازد، به اصطلاح. binding" و. در نتیجه، برنامه نویسی که از وب سرویس استفاده می کند باید چیزی شبیه (شبه کد) بنویسد:

    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 یک سرویس وب صابونی دارد که می توانید با موفقیت (و برخی محدودیت ها) با آن ارتباط برقرار کنید.
  • تغییر خودکار توضیحات یک وب سرویس می تواند همه مشتریان را از بین ببرد. خوب، برای هر سیستمی اینطور است، اگر سازگاری عقب با روش های قدیمی پشتیبانی نشود، همه چیز از بین می رود ...
  • نه یک منفی، بلکه یک نقطه ضعف. همه فراخوانی های متد باید اتمی باشد. به عنوان مثال، هنگام کار با یک پایگاه داده، می توانیم یک تراکنش را شروع کنیم، چندین پرس و جو را اجرا کنیم، سپس rollback یا commit کنیم. هیچ معامله ای در صابون وجود ندارد. یک خواهش، یک جواب، گفتگو تمام شد.
  • پرداختن به توضیحاتی که در سمت سرور وجود دارد (آیا همه چیز به درستی توضیح داده شده است؟) و آنچه در مشتری وجود دارد (آنچه در اینجا برای من توضیح داده شد؟) می تواند بسیار دشوار باشد. چندین بار بود که مجبور شدم با سمت کلاینت سروکار داشته باشم و برنامه نویس سرور را متقاعد کنم که داده های او اشتباه توصیف شده است، اما او اصلاً چیزی در مورد آن نمی فهمید، زیرا تولید خودکار و نباید، این یک موضوع است. نرم افزار. و خطا، طبیعتاً در کد متد بود؛ برنامه نویس به سادگی آن را ندید.
  • تمرین نشان می دهد که توسعه دهندگان وب سرویس ها به طرز وحشتناکی از افرادی که از این خدمات وب استفاده می کنند فاصله دارند. در پاسخ به هر درخواستی (معتبر از خارج)، ممکن است یک خطای نامفهوم "خطای 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 نوع محتوا: text/xml; charset=utf-8 Content-Length: length SOAPAction: "http://webservices.belavia.by/GetAirportsList" ru

جواب خواهد آمد:

HTTP/1.1 200 OK تاریخ: دوشنبه، 30 سپتامبر 2013 00:06:44 GMT سرور: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 4.0.30319 Cache-Control: خصوصی، حداکثر -age=0 نوع محتوا: text/xml; charset=utf-8 Content-Length: 2940

PS قبلاً وب سرویس Aeroflot باز شده بود، اما پس از اینکه 1C پشتیبانی صابون را به 8ku اضافه کرد، دسته ای از آزمایش کننده های بتا 1C آن را با موفقیت نصب کردند. اکنون چیزی در آنجا تغییر کرده است (آدرس را نمی دانم، اگر علاقه دارید می توانید آن را جستجو کنید).
سلب مسئولیت ZZY. او در سطح روزمره صحبت می کرد. می توانید لگد بزنید.

من به این سؤال که چیست نمی پردازم خدمات وبو چرا به آنها نیاز است. مقالات زیادی در این زمینه در اینترنت وجود دارد. من فقط سعی می کنم به طور خلاصه نشان دهم که ایجاد یک کلاینت برای هر وب سرویس در PHP چقدر ساده است.

تنظیمات

برای استفاده صابوندر php باید ماژول SOAP را (که در توزیع php5 موجود است) وصل کنید. در ویندوز، این کار به سادگی انجام می شود - باید اضافه کنید (یعنی اضافه کنید، زیرا این خط فقط در آنجا توضیح داده نمی شود، بلکه به طور کلی گم شده است) php.ini:
extension=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");

Echo 'نرخ مبادله دلار فعلی: ', $نتیجه, ' روبل';
?>

همانطور که از کد می بینید، باید URL سند WSDL را به سازنده کلاس SoapClient ارسال کنید و یک شی را برای کار با وب سرویس مورد نظر دریافت کنید. سپس متدی از این شی فراخوانی می شود که نام آن با نام خود متد وب سرویس یکسان است. این روش نتیجه مورد نظر ما را برمی گرداند.

بنابراین، این مثال ساده اصل ساخت یک کلاینت SOAP برای خدمات وب در PHP را نشان می دهد. با این حال، در یک برنامه واقعی هنوز چیزهای زیادی برای مراقبت وجود دارد، به ویژه این واقعیت که وقتی وب سرویس فراخوانی می شود، ممکن است به طور موقت در دسترس نباشد یا خطایی را برگرداند. به وضوح استفاده از بلوک را پیشنهاد می کند تلاش/گرفتن/پرتاب کردن :)

(PHP 5 >= 5.0.1)

SoapClient::SoapClient — سازنده SoapClient

مولفه های

wsdl

URI از WSDLفایل یا خالیدر صورت کار در غیر WSDLحالت

در طول توسعه، حافظه پنهان WSDL ممکن است با استفاده از آن غیرفعال شود soap.wsdl_cache_ttlتنظیمات php.ini در غیر این صورت تغییرات ایجاد شده در فایل WSDL هیچ تاثیری نخواهد داشت soap.wsdl_cache_ttlباطل شده.

گزینه ها

مجموعه ای از گزینه ها اگر در حالت WSDL کار کنید، این پارامتر اختیاری است. اگر در حالت غیر WSDL کار کنید، محلو اوریگزینه ها باید تنظیم شوند، کجا محلآدرس سرور SOAP برای ارسال درخواست به و اوریفضای نام هدف سرویس SOAP است.

را سبکو استفاده کنیدگزینه ها فقط در حالت غیر WSDL کار می کنند. در حالت WSDL از فایل WSDL می آیند.

را صابون_نسخهگزینه مشخص می کند که آیا از SOAP 1.1 (پیش فرض)، یا SOAP 1.2 کلاینت استفاده شود.

برای احراز هویت HTTP، وارد شدنو کلمه عبورگزینه ها را می توان برای ارائه اعتبار استفاده کرد. برای ایجاد اتصال HTTP از طریق یک سرور پراکسی، گزینه های پروکسی_میزبان, درگاه پروکسی, proxy_loginو proxy_passwordنیز موجود هستند. برای احراز هویت گواهی مشتری HTTPS استفاده کنید local_certو عبارت عبورگزینه ها. احراز هویت ممکن است در احراز هویتگزینه. روش احراز هویت ممکن است یکی باشد SOAP_AUTHENTICATION_BASIC(پیش فرض) یا SOAP_AUTHENTICATION_DIGEST.

را فشرده سازیگزینه اجازه می دهد تا از فشرده سازی درخواست ها و پاسخ های HTTP SOAP استفاده کنید.

را رمزگذاریگزینه رمزگذاری کاراکتر داخلی را تعریف می کند. این گزینه کدگذاری درخواست های SOAP را تغییر نمی دهد (همیشه utf-8 است)، اما رشته ها را به آن تبدیل می کند.

را پی گیریگزینه ردیابی درخواست را فعال می کند تا خطاها را بتوان به عقب ردیابی کرد. این به صورت پیش فرض است نادرست

را نقشه کلاسگزینه می تواند برای نگاشت برخی از انواع WSDL به کلاس های PHP استفاده شود. این گزینه باید یک آرایه با انواع WSDL به عنوان کلید و نام کلاس های PHP به عنوان مقادیر باشد.

تنظیم بولی پی گیریگزینه استفاده از روش های SoapClient->__getLastRequest، SoapClient->__getLastRequestHeaders، SoapClient->__getLastResponse و SoapClient->__getLastResponseHeaders را امکان پذیر می کند.

را استثناهاگزینه یک مقدار بولی است که مشخص می کند آیا خطاهای صابون استثناهایی از نوع SoapFault ایجاد می کنند یا خیر.

را connection_timeoutگزینه یک بازه زمانی برای اتصال به سرویس 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.

را عامل کاربرگزینه رشته ای را برای استفاده در آن مشخص می کند عامل کاربرسرتیتر.

را stream_contextگزینه برای زمینه است.

را امکاناتگزینه یک بیت ماسک از است SOAP_SINGLE_ELEMENT_ARRAYS, SOAP_USE_XSI_ARRAY_TYPE, SOAP_WAIT_ONE_WAY_CALLS.

را زنده بمانگزینه یک مقدار بولی است که تعیین می کند آیا باید ارسال شود اتصال: Keep-Aliveسرصفحه یا اتصال: بستن .

تغییرات

نسخه شرح
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" ,
"password" => "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" ,
"uri" => "http://test-uri/" ,
"style" => SOAP_DOCUMENT ,
"use" => SOAP_LITERAL ));

$client = new SoapClient("some.wsdl" ,
آرایه("فشرده سازی" => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP ));

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

کلاس MyBook(
عمومی $title ;
public $author ;
}

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

?>

کریس گوناواردنا

برای نظارت بر تماس های SOAP در داخل و خارج از سرور یونیکس:

Sudo tcpdump -nn -vv -A -s 0 -i eth0 dst یا میزبان src xxx.xxx.xxx.xxx و پورت 80

و همیشه از "cache_wsdl" => WSDL_CACHE_NONE استفاده کنید

svenr در selfhtml dot org

گزینه "classmap" در واقع یک نقشه برداری از "ComplexType" مورد استفاده در SOAP به کلاس های PHP شما است.

نام تگ های XML که برای درخواست شما بازگردانده شده است را با این ComplexType ها اشتباه نگیرید. SOAP به آنها اجازه می دهد تا متفاوت باشند.

من چیزی شبیه این داشتم:
...


FooBar

TagName کلیدی نیست که می خواهید در نقشه کلاس خود قرار دهید، شما باید نام ComplexType را بدانید که این TagName به آن اشاره دارد. این اطلاعات در منبع WSDL موجود است.

paulovitorbal در gmail dot com

هنگام استفاده از گواهی ها، در پارامتر "local_cert" از محتوای فایل استفاده کنید نه نام فایل.

جدید soapclient("http://localhost/index.php?wsdl ", array("local_cert"=>file_get_contents("./key.pem"),"passphrase"=>"password"));

در PHP، می توانید ویژگی های خصوصی را در کلاس هایی که در کلاس مپ خود استفاده می کنید تعریف کنید. بنابراین اگر یک ویژگی خصوصی $foo را در کلاس خود ایجاد کنید، و عنصر SOAP یک عنصر فرزند دارد ، محتویات $foo روی محتویات تنظیم می شود . به این ترتیب می توانید دسترسی به ویژگی های کلاس های خود را کنترل کنید.

(توجه: این در HPHP فیس بوک کار نمی کند).

wilem dot stuursma در hyves dot nl

اگر می‌خواهید از کلاس‌ها در فضای نام متفاوتی در نقشه کلاس خود استفاده کنید، فقط از بک اسلش در نام کلاس هدف استفاده کنید.

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

شما باید دوبار بک اسلش را مشخص کنید زیرا کاراکتر فرار در رشته ها است.

simonlang در gmx dot ch

مثال برای یک سرویس گیرنده صابون با احراز هویت HTTP از طریق یک پروکسی:

SoapClient جدید(
"service.wsdl"،
آرایه(
// مواردی برای توسعه.
"ردیابی" => 1،
"exceptions" => درست است،
"cache_wsdl" => WSDL_CACHE_NONE،
"features" => SOAP_SINGLE_ELEMENT_ARRAYS،

// اعتبارنامه برای درخواست SOAP.
"login" => "نام کاربری" ,
"password" => "password" ,

// آدرس پروکسی.
"proxy_host" => "example.com" , // طرحواره را در اینجا اضافه نکنید (http یا https). این کار نخواهد کرد.
"proxy_port" => 44300،

// تأیید اعتبار برای پروکسی.
"proxy_login" => NULL،
"proxy_password" => NULL،
);
?>
ارائه URL به یک فایل WSDL در سرور راه دور (که با احراز هویت HTTP نیز محافظت می شود) کار نکرد. من WSDL را دانلود کردم و آن را در سرور محلی ذخیره کردم.

آصاف ملر

یک پیکربندی کامل صابون .net php:
یادداشت
1. web.config در سرور .net باید با basehttp binding کار کند.
2. پارامترهای عملکرد صابون باید به صورت زیر ارسال شوند:
آرایه("parm1_name"=>"parm1_value",
"parm2_name"=>"parm2_value"...)

header("Content-Type: text/plain");

تلاش كردن (
$options = آرایه(
"soap_version" => SOAP_1_1،
"exceptions" => درست است،
"ردیابی" => 1،
"cache_wsdl" => WSDL_CACHE_NONE
);
$client = SoapClient جدید ( "http://www.example.com/end_point.wsdl"، $options)؛

) catch ( استثنا $e ) (
پژواک"

خطای استثنا!

" ;
echo $e -> getMessage();
}

اکو "اجرای HelloWorld:" ;

تلاش كردن (
$response = $client -> HelloWorld();

}
گرفتن (استثنا $e)
{
echo "Caught استثنا: " , $e -> getMessage (), "\n" ;
}

Print_r($response);
?>
موفق باشید!
آصاف.

faebu در faebu dot 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) (
if (isset($options [ "wdsl_local_copy" ]) &&
$options [ "wdsl_local_copy" ] == درست &&
isset($options [ "ورود به سیستم" ]) &&
isset($options [ "رمز عبور" ])) (

$file = md5(uniqid()). ".xml" ;

اگر (($fp = fopen ($this -> cache_dir . $file , "w" )) == false ) (
پرتاب استثنای جدید ( "نمی توان فایل WDSL محلی ایجاد کرد (". $this -> cache_dir . $file. ")");
}

$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، $ اعتبار)؛
curl_setopt($ch، CURLOPT_TIMEOUT، 15);
curl_setopt ($ch، CURLOPT_FILE، $fp)؛
اگر (($xml = curl_exec ($ch )) === نادرست ) (
//curl_close($ch);
fclose($fp);
unlink ($this -> cache_dir . $file );

پرتاب جدید Exception(curl_error($ch));
}

Curl_close ($ch);
fclose($fp);
$wdsl = $this -> cache_url . $file ;
}

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

Echo $wdsl ;
والد :: __construct ($wdsl، $options);

لغو پیوند ($this -> cache_dir . $file );
}
}
?>

tatupheba در gmail dot com

سلام مردم!

یک نکته برای توسعه دهندگان:

هنگام برنامه نویسی برخی از سرورهای صابون، دستور "soap.wsdl_cache_enabled" را در فایل php.ini روی 0 تنظیم کنید:

Soap.wsdl_cache_enabled=0

در غیر این صورت یک دسته از خطاهای عجیب و غریب می دهد که می گویند wsdl شما نادرست است یا گم شده است.

انجام این کار شما را از بسیاری از دردهای بیهوده نجات می دهد.

titan در phpdevshell dot org

لازم به ذکر است که در صورت دریافت خطای بازگشتی: "Object reference to a instance of an object set not set to an instance of an object.". این می تواند به دلیل چیزی به سادگی عبور دادن پارامترهای نادرست باشد. وقتی به این XML نگاه می کنید:



رشته
زمان قرار
زمان قرار

کد شما باید چیزی شبیه به این باشد:

تلاش كردن (
$options = آرایه(
"soap_version" => SOAP_1_2،
"exceptions" => درست است،
"ردیابی" => 1،
"cache_wsdl" => WSDL_CACHE_NONE
);
$client = SoapClient جدید ( "http://example.com/doc.asmx?WSDL"، $options)؛
// توجه داشته باشید که تگ های «دریافت» و «درخواست» در کجای XML قرار دارند
$results = $client -> Get (array("request" =>array("CustomerId" => "1234" )));
) catch ( استثنا $e ) (
پژواک"

خطای استثنا!

" ;
echo $e -> getMessage();
}

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

اگر فایل WSDL شما حاوی پارامتری با نوع base64Binary است، نباید از base64_encode() هنگام عبور از ورقه های صابون خود استفاده کنید. هنگام انجام درخواست، کتابخانه SOAP به طور خودکار داده های شما را به نام base64 رمزگذاری می کند، در غیر این صورت شما دو بار آن را رمزگذاری خواهید کرد.

قطعه WSDL:

$string = "داده‌هایی که می‌خواهید_ارسال کنید___like_xml_in_soap";
$soap_data = آرایه(
"foo" => "bar" ,
//"content" => base64_encode($string) // این کار را نکنید
"content" => $string //این کار را انجام دهید
);
$response = $client -> Send ($soap_data );
?>

marcovtwout در hotmail dot com

از آنجایی که با SOAP جدید بودم، مدتی جستجو می کردم تا بفهمم چرا پیام من در soapUI پاسخ می دهد، اما نه با کد php من. سرویس خاصی که به آن آدرس می‌دادم یک HTTP 202 Accepted در صورت موفقیت (بدون پاسخ) می‌دهد، اما یک پیام SOAP را در مورد خطاها برمی‌گرداند.

وضعیت:
با استفاده از یک اتصال کلاینت (تایید شده) و یک فایل WDSL، تماس‌های SOAP با نوع «One-Way» سرصفحه پاسخی نمی‌دهند، حتی اگر پاسخ مورد انتظار باشد.

راه حل:
هنگام فراخوانی سازنده کلاینت، SOAP_WAIT_ONE_WAY_CALLS را در $options["features"] تنظیم کنید.

تیم در tdinnet dot com

به نظر می رسد PHP 5.2.11 در مورد صحت یک WSDL چندان حساس نیست.

سایر مشتریان SOAP از مشکلات طرحواره و فضای نام شکایت داشتند، در حالی که SoapClient PHP کاملاً خوب کار می کرد. با این حال، رفع این مشکلات برای سایر کلاینت ها باعث شد تا SoapClient PHP به حدی برسد که اشیاء ارسال شده به متد SOAP به آرایه های خالی تبدیل شوند. سمت سرور.

درس آموخته شده: برخی از عناصر با xsd پیشوند شده بودند: و برخی دیگر نه -- مطمئن شوید که WSDL شما صحیح و سازگار است (من از یک WSDL_Gen.php بهینه شده استفاده می کنم).

جیمز دات الیس در جیمیل دات کام

من برای دریافت پاسخ از یک سرور SOAP Coldfusion با مشکل مواجه بودم، بدون اینکه مشکل واضحی در SoapClient استفاده شده باشد.

در نهایت متوجه شدم که سرور فقط درخواست های SOAP 1.1 را می پذیرد و نه 1.2. مطمئن نیستم که آیا این یک تنظیم کلدفیوژن در کل سیستم است یا خیر، اما اگر به همان دیوار برخورد کردید، گزینه SoapClient "soap_version" را روی ثابت SOAP_1_1 تنظیم کنید (که پیش‌فرض است اما من به‌طور پیش‌فرض روی 1.2 تنظیم می‌شد زیرا کلاینت برای سرویس دیگری استفاده می‌شد. )

ajcartmell در fonant dot com

به نظر می‌رسد مشکلی در تعیین رشته‌های خالی برای گزینه‌های proxy_host و proxy_port در نسخه‌های اخیر PHP (از نسخه‌های بالاتر از 5.2.9 و مساوی یا زودتر از 5.2.11) وجود دارد.

ارائه مقادیر رشته خالی برای proxy_host و proxy_port باعث ایجاد خطاهای نوع "host not found" می شود: ارائه NULL یا FALSE به خوبی کار می کند.

bhargav dot khatana در gmail dot com

بیش از یک هفته طول کشید تا بفهمم چگونه سرفصل‌های WSSE (امنیت سرویس وب) را در PHP SOAP بومی پیاده‌سازی کنم. هیچ منبع زیادی در این مورد در دسترس نیست، بنابراین فکر کنید برای منافع جامعه این را در اینجا اضافه کنید.

مرحله 1: دو کلاس ایجاد کنید تا ساختاری برای هدرهای WSSE ایجاد کنید

کلاس clsWSSEAuth(
خصوصی $Username ;
خصوصی $Password ;
تابع __construct ($username، $password) (
$this -> Username = $username ;
$this -> Password = $password ;
}
}

کلاس clsWSSEToken (
خصوصی $UsernameToken ;
تابع __construct ($innerVal)(
$this -> UsernameToken = $innerVal ;
}
}
?>
مرحله 2: متغیرهای Soap را برای نام کاربری و رمز عبور ایجاد کنید

$username = 1111 ;
$password = 1111 ;

//با ارائه دهنده خود بررسی کنید که از کدام فضای نام امنیتی استفاده می کند.
$strWSSENS = "http://schemas.xmlsoap.org/ws/2002/07/secext";

$objSoapVarUser = SoapVar جدید ($username, XSD_STRING, NULL, $strWSSENS, NULL, $strWSSENS);
$objSoapVarPass = new SoapVar($password, XSD_STRING, NULL, $strWSSENS, NULL, $strWSSENS);
?>
مرحله 3: برای کلاس Auth Object ایجاد کنید و در soap var عبور دهید

$objWSSEAuth = clsWSSEAuth جدید ($objSoapVarUser , $objSoapVarPass );
?>
مرحله 4: SoapVar را از شیء کلاس Auth ایجاد کنید

$objSoapVarWSSEAuth= SoapVar جدید ($objWSSEAuth , SOAP_ENC_OBJECT , NULL , $strWSSENS , "UsernameToken" , $strWSSENS );
?>
مرحله 5: ایجاد شی برای کلاس Token

$objWSSEToken = جدید clsWSSEToken ($objSoapVarWSSEAuth );
?>
مرحله 6: SoapVar را از شی کلاس Token ایجاد کنید

$objSoapVarWSSEToken= SoapVar جدید ($objWSSEToken، SOAP_ENC_OBJECT، NULL، $strWSSENS، "UsernameToken"، $strWSSENS);
?>
مرحله 7: SoapVar را برای گره "Security" ایجاد کنید

$objSoapVarHeaderVal=SoapVar جدید ($objSoapVarWSSEToken، SOAP_ENC_OBJECT، NULL، $strWSSENS، "امنیت"، $strWSSENS);
?>
مرحله 8: شی هدر را از soapvar امنیتی ایجاد کنید

$objSoapVarWSSEHeader= SoapHeader جدید ($strWSSENS، "امنیت"، $objSoapVarHeaderVal، درست، "http://abce.com");

//پارامتر سوم در اینجا "mustUnderstand=1" را می سازد
//پارامتر Forth "actor="http://abce.com"" را تولید می کند
?>
مرحله 9: شیء Soap Client را ایجاد کنید

$objClient = SoapClient جدید ($WSDL، $arrOptions)؛
?>
مرحله 10: هدرها را برای شیء soapclient تنظیم کنید

$objClient -> __setSoapHeaders (آرایه($objSoapVarWSSEHeader ));
?>
مرحله 11: فراخوانی نهایی متد

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

پیتر در وب کوستیک دات کام

متوجه شدم که واکشی WSDL هنگام استفاده از احراز هویت اولیه در soapclient ناموفق است. بنابراین راه حل زیر را با استفاده از 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 جدید واکشی کنید
if(! file_exists ($cache_file ) || filectime ($cache_file )< time () - 3600 ) {
$agent = escapeshellarg("--user-agent=($g["usagent"])");
mwexec("wget‎--quiet --timeout=5 ($agent) --no-check-certificate --output-document=( $cache_file ) ( $url ) " );
if(! file_exists ($cache_file )) (
پرتاب جدید استثنا ("WSDL در ( $url ) بارگیری نشد" );
}
}
برگشت
$cache_file ;
}
?>

meltir در meltir dot com

برای کسانی که با سرورهای پروکسی تأیید شده NTLM مبارزه می کنند، در اینجا راه حلی وجود دارد که من از ATM استفاده می کنم:

/**
* فرزند SoapClient با پشتیبانی از احراز هویت پروکسی ntlm
*
* @author Meltir
*
*/
کلاس NTLM_SoapClient SoapClient را گسترش می دهد (

تابع عمومی __construct ($wsdl، $options = array()) (
if (empty($options [ "proxy_login" ]) || خالی ($options [ "proxy_password" ])) Exception جدید را پرتاب کنید ( "ورود و رمز عبور برای احراز هویت NTLM لازم است!");
$this -> proxy_login = $options [ "proxy_login" ];
$this -> proxy_password = $options [ "proxy_password" ];
$this -> proxy_host = (خالی($options [ "proxy_host" ]) ? "localhost": $گزینه ها[ "proxy_host"]);
این $-> درگاه پروکسی=(خالی($گزینه ها[ "درگاه پروکسی"]) ? 8080 : $گزینه ها[ "درگاه پروکسی"]);
والدین:: __ساختن($wsdl, $گزینه ها);
}

/**
* با استفاده از curl با ntlm auth یک URL تماس بگیرید
*
* @param string $url
* @param string $data
* رشته بازگشت @
* @پرتاب SoapFault در خطای اتصال حلقه
*/
عملکرد محافظت شدهcallCurl($url, داده $) {
$ handle= curl_init();
curl_setopt($ handle, CURLOPT_HEADER, نادرست);
curl_setopt($ handle, CURLOPT_URL, $url);
curl_setopt($ handle, CURLOPT_FAILONERROR, درست است، واقعی);
curl_setopt($ handle, CURLOPT_HTTPHEADER،آرایه("کلینت PHP SOAP-NTLM"));
curl_setopt($ handle, CURLOPT_RETURNTRANSFER, درست است، واقعی);
curl_setopt($ handle, CURLOPT_POSTFIELDS, داده $);
curl_setopt($ handle, CURLOPT_PROXYUSERPWD, این $-> proxy_login. ":" . این $-> proxy_password);
curl_setopt($ handle, CURLOPT_PROXY, این $-> پروکسی_میزبان. ":" . این $-> درگاه پروکسی);
curl_setopt($ handle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
$response= curl_exec($ handle);
اگر (خالی)
$response)) {
جدید پرتاب
Soap Fault("خطای CURL:". curl_error($ handle), curl_errno($ handle));
}
curl_close($ handle);
برگشت
$response;
}

عملکرد عمومی __doRequest(درخواست $, مکان $, $ اقدام, نسخه $, $one_way= 0 ) {
برگشت
این $-> callCurl(مکان $, درخواست $);
}

}
?>

نیاز به فر دارد و می تواند گسترش یابد، اما برای نیازهای ساده من کار می کند.

eric dot caron در gmail dot com

فکری که توسط jan در bestbytes اشاره شد و در باگ شماره 27777 مورد بحث قرار گرفت، یکی از منابع رایج "تجزیه WSDL: پیدا نشد" "خطا ناشی از تلاش برای دسترسی به یک WSDL است که با احراز هویت HTTP محافظت می شود. ارسال ورود به سیستم/رمز عبور در پارامتر دوم همیشه کار نمی کند. بنابراین اگر با این پیغام خطا مواجه شدید و سعی در دسترسی به یک فایل WSDL محافظت شده دارید، نام کاربری و رمز عبور را با پارامتر اول وارد کنید.

ناشناس

هنگام تلاش برای استفاده از سرویس های وب استاندارد Parlay X بدون موفقیت، مجبور شدم با یک رفتار نسبتاً عجیب دست و پنجه نرم کنم. با این حال، من یک راه حل برای مشکل خود پیدا کردم.

مشکلی که من با آن روبرو شدم مربوط به یک درخواست احراز هویت اولیه HTTP نامعتبر بود که به وب سرویس ارسال شد. با وجود اینکه مدارک درست را ارسال می کردم، با خطای احراز هویت مواجه می شدم. به نظر می رسد که PHP درخواست های HTTP را به نقطه پایانی دیگری ارسال می کرده است که مستقیماً از طریق وب سرویس در معرض دید قرار نمی گیرد و آن نقطه پایانی نیازی به احراز هویت ندارد.

راه حل من برای آن مشکل با استفاده از این خطوط ساده در مثال استفاده از روش sendSms Paraly-X بود.

اول، ایجاد یک مشتری صابون بدون هیچ گونه گزینه احراز هویت HTTP:

مشتری $= جدیدSoapClient($wsdl_url);
?>

درخواست بالا wsdl را در پوشه /tmp کش می کند. بلافاصله پس از ساخت، ما یک مشتری صابون دیگری ایجاد می کنیم، این بار با گزینه های احراز هویت HTTP:

تلاش كردن (
مشتری $= جدیدSoapClient($wsdl_url، آرایه("وارد شدن"=> "گریفین",
"کلمه عبور"=> "کلمه عبور"));
) گرفتن (
استثنا $e) {
printf("خطا:sendSms: %s\n", $e-> __toString());
برگشت
نادرست;
}
?>

حالا باید بدون مشکل کار کند. بدون تماس دوم، PHP sendSms را بدون اعتبار تماس می‌گیرد که منجر به تلاش ناموفق به دلیل گم شدن اطلاعات احراز هویت می‌شود. به نظر من این روش ساده ترین است.

این فرآیند باید هر بار که wsdl کش شده منقضی می شود انجام شود، یا به سادگی می توان زمان زنده بودن wsdl کش شده را از php.ini افزایش داد.

جان دات گیلبرت در net-entwicklung dot de

توجه داشته باشید که ایجاد یک سرویس گیرنده صابون برای یک URL نامعتبر (شما آزمایش می کنید که وقتی یک سرویس در دسترس نیست، چه اتفاقی می افتد، درست است؟) معمولاً استثنایی ایجاد می کند که با try..catch قابل تشخیص است. با این حال، اگر xdebug فعال باشد، یک خطای مرگبار دریافت خواهید کرد، که واضح است که نمی توان آن را گرفت.

sloloem در gmail dot com

من در بحث استفاده از نقشه کلاسی مشکلی داشتم که فهمیدن آن مدت زیادی طول کشید. من فرض می‌کردم که نوع WSDL که اسناد به آن اشاره می‌کنند، نام عنصری است که در SOAP برگردانده می‌شود، بنابراین مانند:

و من تعجب کردم که چرا نقشه برداری
"classmap"=>آرایه("node"=>"MyNode")

هیچ کاری نکرد
این به این دلیل است که در WSDL من گره را به صورت زیر تعریف کردم:

نقشه کلاسی که نیاز داشتم این بود:
"classmap"=>آرایه("nodeType"=>"MyNode")

من توانستم نام نوع ها را با استفاده از SoapClient->__getTypes پیدا کنم
بعداً متوجه شدم که کجا می توانم در داخل WSDL برای نام تایپ مورد نیازم جستجو کنم.

نمی‌دانم چیزی به‌طور دردناکی را از دست داده‌ام یا نه، اما شاید این بتواند برخی از اسناد را پاک کند.

جان

ما با استفاده از SoapClient برای اتصال به سرور خارجی از طریق Microsoft ISA (در حال حاضر نسخه 2006 اما این ممکن است برای نسخه‌های دیگر نیز اعمال شود) مشکلاتی داشتیم. به عنوان "ناشناس" ثبت می شود.

Sysadmin ما معتقد است که این به این دلیل است که PHP اطلاعات NTLN (پروتکل امنیتی ویندوز) را با فرمت صحیح ارائه نمی دهد (و اینکه آیا باید با پراکسی های اختصاصی کار کند البته بحث دیگری است). ما "نام کاربری"، "DOMAIN\username" را امتحان کردیم بدون تاثیر. راه حل این است که یک استثنا در سرور ISA برای نام میزبان/IP هدف اضافه کنیم؛ سپس null را می توان برای proxy_login و proxy_password ارائه کرد و سپس اتصال باید کار کند. همانطور که انتظار میرفت.

در یک نکته مرتبط، اگر مشکل دارید، مطمئن شوید که شماره پورت به صورت یک عدد صحیح ارائه شده است. اگر شماره پورت به صورت رشته ای ارائه شود، برخی از نسخه های PHP از پروکسی با SoapClient استفاده نمی کنند.

jan at bestbytes dot de

در صورت نیاز به احراز هویت اولیه، می توانید یک wsdl دریافت کنید:

$login = "برت";
رمز عبور $= رمز عبور برتس;

مشتری $= جدیدSoapClient(
"http://". کد urlencode($login) . ":" . کد urlencode(رمز عبور $) . "@www.server.com/path/to/wsdl",
آرایه(
"وارد شدن"=> $login,
"کلمه عبور"=> رمز عبور $
)
);

?>

اطلاعات در nicksilvestro dot net

برای هر کسی که با ArrayOf_xsd_string مشکل دارد و خطای مشابه "No deserializer defined for array type (http://www.w3.org/2001/XMLSchema)string" را دریافت می کند.
سعی کنید از پارامتر "ویژگی‌ها" استفاده کنید، روی SOAP_USE_XSI_ARRAY_TYPE تنظیم کنید - این اطمینان حاصل می‌کند که از سریال‌زدایی صحیح استفاده می‌شود.

به عنوان مثال،
مشتری $= جدیدSoapClient("some.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 در gmail dot com

استثناء SoapFault: به نظر می‌رسد هیچ سند XML وارد نشده است قبلاً ذکر شده است که زمانی رخ می دهد که سرور شما قبلاً چیزی را خروجی می دهد ... > برچسب زدن.

برای همه کسانی که با آن مشکل دارند، وعدم دسترسی به کد سرور:
این نحوه ساخت پروکسی است که پاسخ ها را پاک می کندبرایشما

php
/**
* کلاس ساده برگرفته از یادداشت جیمز الیس
*/
کلاسProxy_Clientگسترش می یابدSoapClient{
حفاظت شده
$cacheDocument= "" ;
عملکرد عمومی
__ساختن($wsdl, $گزینه ها) {
والدین:: __ساختن($wsdl, $گزینه ها);
}

/**
* SetCacheDocument() محتویات سند ذخیره شده قبلی را تنظیم می کند
*/
عملکرد عمومیSetCacheDocument($ سند) {
این $-> cacheDocument= $ سند;
}

/**
* __doRequest() SoapClient استاندارد را برای رسیدگی به درخواست محلی لغو می کند
*/
عملکرد عمومی__doRequest() {
برگشت
این $-> cacheDocument;
}
}

//این کد را در تابع خود یا هر جایی که همه متغیرهای مورد نیاز را تنظیم کرده اید قرار دهید

مشتری $= جدیدSoapClient($wsdl_url, $settings_array);
$ void= مشتری $-> روش $($params); //برای دریافت پاسخ از سرور با این تماس بگیرید

$response_string= مشتری $-> __getLastResponse();

//این قسمت موارد را حذف می کند
شروع $= strpos($response_string, ");
$end= strrpos($response_string, ">" );
$response_string= substr($response_string, شروع $, $end- شروع $+ 1 );

//پراکسی خود را آماده کنید
پروکسی $= جدیدProxy_Client($wsdl_url, $settings_array);
//و آن را با پاسخ سرور پر کنید
پروکسی $-> SetCacheDocument($response_string);

$and_finally_the_result_is= پروکسی $-> روش $($params);

print_r($and_finally_the_result_is); //این به شما امکان می‌دهد ببینید چه چیزی وجود دارد

?>

$method نام روش است به عنوان مثال $method="getVersion";
$params - پارامترهای معمولی برای روش صابون

نکاتی برای کاربران:

    اگر فایل WSDL را می‌شناسید، می‌توانید با استفاده از یک پیوند سریع به فرم‌های مشتری راه‌اندازی کنید
    http://www.?template=/clientform.html&fn=soapform
    &SoapTemplate=هیچ&SoapWSDL=فایل_WSDL_شما
    یا
    http://www..html?SoapWSDL=Your_WSDL_File

    سرور فایل های WSDL را در عملیات عادی ذخیره می کند تا عملکرد را بهبود بخشد. اگر تغییری در فایل WSDL ایجاد کردید، آن را انتخاب کنید خیرچک باکس

نکاتی برای توسعه دهندگان:

    استفاده کنید<مستندات> در صورت امکان در فایل WSDL خود دستورالعمل ها را ارائه دهید. در فرم مشتری نمایش داده خواهد شد.

    اگر عنصری دارای تعداد ثابتی از مقادیر باشد، از نوع شمارش استفاده کنید. آنها به عنوان جعبه های کشویی نمایش داده می شوند.

ویژگی های کلیدی:

    از طرح XML 1999 و 2001 پشتیبانی کنید. این ابزار از طرح تعریف شده در فایل WSDL برای ساخت درخواست های SOAP استفاده می کند.

    پشتیبانی از آرایه و آرایه از ساختارها. فقط آرایه های تک بعدی پشتیبانی می شوند. متأسفیم، هیچ آرایه پراکنده ای وجود ندارد.

    قابلیت سریال‌سازی انواع داده‌های پیچیده و آرایه‌ای از انواع داده‌های پیچیده، حتی ساختارهای تعبیه‌شده چند سطحی.

    مدیریت ID/HREF هم در پیام های SOAP و هم در تعاریف طرحواره.

    پشتیبانی از هر دو بخش SOAP 5/7 و رمزگذاری سند / تحت اللفظی..

جزییات فنی- اتصال پویا خدمات SOAP

Binding یک قرارداد بین منطق مشتری و منطق سرور است. دو نوع اتصال در SOAP وجود دارد: اتصال شی (یا SOAP binding) و اتصال پارامتر. اکثر جعبه‌های ابزار SOAP با تولید اشیاء پراکسی سمت کلاینت، اتصالات شی ثابت را انجام می‌دهند. مشکل اینجاست که بر خلاف ماژول برنامه نویسی سنتی که در آن اشیا/رابط ها پایدار هستند، سرویس های وب در هر لحظه بدون اطلاع قبلی در معرض تغییر هستند، زیرا اغلب تحت مالکیت/کنترل شخص ثالث هستند. مشکل دیگر زمانی رخ می دهد که تعداد سرویس های وب قابل دسترسی افزایش می یابد، کد منبع تولید شده می تواند به سرعت تبدیل به یک کابوس تعمیر و نگهداری شود. در نهایت، زمانی که سرویس‌های وب قابل دسترسی ناشناخته هستند، که اغلب احتمال دارد، اتصال اولیه غیرممکن یا حداقل دشوار می‌شود. تولید یک شیء پراکسی برای سرویسی که در آینده ساخته می شود یک پروژه تحقیقاتی جالب است.

کلاینت SOAP عمومی اتصالات پویا (یا اتصالات زمان اجرا) خدمات و پارامترهای SOAP را نشان می دهد. یک شی در زمان اجرا زمانی که فایل WSDL مشخص شده است تولید می‌شود و مقادیر پارامتر دقیقاً قبل از تحویل با پیام SOAP مرتبط می‌شود. تکنیک اتصال دیرهنگام (یا اتصال تاخیری) می تواند هزینه تعمیر و نگهداری را تا حد زیادی کاهش دهد، زیرا می توان از یک مشتری واحد برای دسترسی به بسیاری از خدمات وب استفاده کرد.

خطا:محتوا محفوظ است!!