PHP: полный мануал с примерами, функциями и ООП
Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Дерево руководства
Глава 115 · От первого вызова до эксплуатации
SOAP в PHP: полный справочник клиента, сервера, WSDL, типов и ошибок
От первого локального Envelope до WSDL-клиента, production endpoint, SOAP Fault, headers, типизации, cache и диагностики. Полная официальная ветвь book.soap с 46 узлами и практическим маршрутом.
SOAP без профессиональной деформации: от заказа к Envelope и обратно
Осязаемая цель. Есть старый сервис перевозчика, банка или ERP: он принимает XML Envelope, выполняет операцию и возвращает XML/Fault. После первой главы вы сможете вызвать sum одной строкой, увидеть реальный request/response и понять, где искать сбой: в PHP-значении, SOAP XML, HTTP или удалённой логике.
Граница модели. Стрелки показывают логические слои, а не отдельные процессы: клиент и сервер могут находиться на разных машинах, а WSDL может загружаться до первого вызова и кэшироваться. SOAP не «вызывает PHP-функцию через интернет» напрямую: между ними остаются XML, HTTP и договор.
Маршрут от задачи
| Если вам нужно | С чего начать | Что проверить следующим |
|---|---|---|
| Подключиться к готовому WSDL | SoapClient::__construct | SoapClient::__getFunctions и SoapClient::__getTypes |
| Отправить одну операцию | SoapClient::__soapCall | SoapClient::__getLastRequest и обработка Fault |
| Добавить auth/correlation header | SoapHeader::__construct | SoapClient::__setSoapHeaders |
| Опубликовать PHP endpoint | SoapServer::__construct | SoapServer::addFunction/SoapServer::setClass → SoapServer::handle |
| Объяснить «Could not connect» | SoapClient::__getLastRequestHeaders | разделение WSDL download, DNS/TLS/connect/read timeout и call |
| Сохранить состояние между calls | SoapServer::setPersistence | SoapClient::__getCookies и session boundary |
Установка и конфигурация как четыре проверяемых слоя
Чтобы пример заработал, нужны четыре независимых слоя. Ошибка «SOAP не работает» без указания слоя ничего не диагностирует.
| Слой | Что даёт | Как проверить |
|---|---|---|
| PHP/SAPI | Запускает код CLI/FPM/Apache. | PHP_VERSION; CLI и web могут читать разные ini. |
| ext/soap | SoapClient/SoapServer/value objects. | extension_loaded("soap"). |
| libxml/XML | Разбор WSDL/XSD/Envelope. | extension_loaded("libxml"); valid XML/import paths. |
| Сеть/endpoint | DNS, TLS, proxy, connect/read. | Отдельно получить WSDL и отдельно вызвать operation; сравнить окружения. |
- Проверить extension в том же SAPI.
- Загрузить главный WSDL и все imports.
- Получить список operations/types.
- Сделать локальный loopback call.
- Только затем проверять удалённый endpoint/auth/TLS.
Требования: libxml, поддерживаемый SOAP/WSDL и доступность всех импортов
Официальное расширение опирается на libxml и поддерживает подмножества SOAP 1.1, SOAP 1.2 и WSDL 1.1. «Подмножество» означает: конкретный vendor contract надо прогнать на выбранной версии PHP; одной надписи WSDL 1.1 недостаточно.
- XML well-formedness: namespace URI, QName и encoding значимы; красивый префикс ns1 — нет.
- WSDL/XSD reachability: главный файл может импортировать другие схемы с отдельными URL/TLS/DNS.
- Transport: ext/soap выполняет HTTP; firewall, proxy, SELinux/container policy живут вне WSDL.
- Contract data: minOccurs/maxOccurs, nillable, wrapper style и fault messages важнее PHP var_dump.
Перед интеграцией запросите у поставщика версию WSDL, test endpoint, тестовые credentials, sample request/response, список faults, timeout/rate-limit/idempotency policy и правила изменения контракта.
Установка ext/soap: включить в том процессе, который обслуживает код
В Windows DLL уже входит в локальный PHP 8.5.11 этого проекта. Для изоляции она загружается только в дочернем процессе: php -d extension=/absolute/path/php_soap.dll script.php. Общий php.ini и публичный сайт не меняются.
| Среда | Установка/включение | После изменения |
|---|---|---|
| Сборка PHP из исходников | ./configure --with-libxml --enable-soap ..., затем обычные make/install шаги вашей сборки. | Проверить build flags и php -m. |
| Debian / Ubuntu package | apt install php-soap либо versioned пакет вроде php8.5-soap, если он есть в выбранном repository. | Перезапустить нужный PHP-FPM pool или Apache; CLI перечитывает ini при новом запуске. |
| RHEL / Fedora package | dnf install php-soap из repository, совместимого с установленным PHP. | Перезапустить FPM или Apache и проверить модуль через web SAPI. |
| Windows ZIP PHP | Убедиться, что есть ext/php_soap.dll, и добавить extension=soap в ini конкретного SAPI. | Новый CLI process; для Apache/FastCGI — restart соответствующего процесса. |
| Проверка | Команда/код | Ожидаемый смысл |
|---|---|---|
| Модуль загрузился | php -d extension=php_soap.dll -m | В списке есть soap. |
| Версия совпала | phpversion("soap") | На стенде 8.5.11. |
| Классы доступны | class_exists(SoapClient::class) | true в том же процессе. |
| CLI ini | php --ini | Путь CLI может отличаться от FPM/Apache. |
| FPM / Apache SAPI | php_ini_loaded_file() и extension_loaded("soap") в закрытом healthcheck | Не полагаться на успешный CLI, если запрос обслуживает другой SAPI. |
Runtime configuration и WSDL cache без магических очисток
WSDL cache сохраняет разобранный контракт, а не ответы операций. Поэтому «операция старая» после deploy может быть cache issue, а «медленный call» после быстрого конструктора — уже endpoint/transport issue.
| INI | Тип | Documented default | Changeability | Локальное 8.5.11 | Договор |
|---|---|---|---|---|---|
soap.wsdl_cache_enabled | int | 1 | INI_ALL | 1 | Главный переключатель WSDL cache. |
soap.wsdl_cache_dir | string | /tmp | INI_ALL | /tmp | Каталог disk cache; web process должен иметь безопасные права. |
soap.wsdl_cache_ttl | int | 86400 | INI_ALL | 86400 | Срок записи в секундах; 86400 = сутки. |
soap.wsdl_cache | int | 1 | INI_ALL | 1 | Стратегия: 0 none, 1 disk, 2 memory, 3 both. |
soap.wsdl_cache_limit | int | 5 | INI_ALL | 5 | Максимум in-memory WSDL entries. |
INI_ALL означает, что значение можно менять на уровнях, допускаемых PHP INI_ALL, включая runtime через ini_set(). Это не делает изменение безопасным посреди long-lived worker: cache policy должна быть предсказуемой для всего процесса.
| Среда | Разумная политика |
|---|---|
| Разработка меняющегося WSDL | cache_wsdl=WSDL_CACHE_NONE на клиенте либо короткий контролируемый TTL; не удалять чужие cache files. |
| Production immutable/versioned WSDL | Disk/memory cache уменьшает download/parse; обновление проходит отдельным deploy/contract test. |
| Long-lived worker | Memory cache живёт с process; после смены WSDL нужен lifecycle/restart согласно deploy policy. |
| Несколько tenants/contracts | Учитывать cache key, URL, credentials/imports; не выдавать один контракт за другой. |
Все 81 предопределённая константа: категории, значение и место применения
Константа — подписанное значение для options/serializer. Совпавшие числа не делают константы взаимозаменяемыми: SOAP_1_1 и SOAP_RPC равны 1, но отвечают на разные вопросы.
| Константа | Значение 8.5.11 | Категория | Где применяется |
|---|---|---|---|
SOAP_1_1 | 1 | Версия | Выбор SOAP 1.1/1.2 в options клиента или сервера. |
SOAP_1_2 | 2 | Версия | Выбор SOAP 1.1/1.2 в options клиента или сервера. |
SOAP_PERSISTENCE_SESSION | 1 | Состояние сервера | Request или PHP-session lifecycle объекта setClass. |
SOAP_PERSISTENCE_REQUEST | 2 | Состояние сервера | Request или PHP-session lifecycle объекта setClass. |
SOAP_FUNCTIONS_ALL | 999 | Экспорт | Deprecated с PHP 8.4: используйте явный массив имён функций. |
SOAP_ENCODED | 1 | Binding | Style/use SOAP binding; в WSDL-mode берётся из контракта. |
SOAP_LITERAL | 2 | Binding | Style/use SOAP binding; в WSDL-mode берётся из контракта. |
SOAP_RPC | 1 | Binding | Style/use SOAP binding; в WSDL-mode берётся из контракта. |
SOAP_DOCUMENT | 2 | Binding | Style/use SOAP binding; в WSDL-mode берётся из контракта. |
SOAP_ACTOR_NEXT | 1 | Роли Header | Предопределённая роль/actor для обработки SOAP Header. |
SOAP_ACTOR_NONE | 2 | Роли Header | Предопределённая роль/actor для обработки SOAP Header. |
SOAP_ACTOR_UNLIMATERECEIVER | 3 | Роли Header | Предопределённая роль/actor для обработки SOAP Header. |
SOAP_COMPRESSION_ACCEPT | 32 | HTTP compression | Комбинируется в option compression; уровень 1–9 добавляется отдельно. |
SOAP_COMPRESSION_GZIP | 0 | HTTP compression | Комбинируется в option compression; уровень 1–9 добавляется отдельно. |
SOAP_COMPRESSION_DEFLATE | 16 | HTTP compression | Комбинируется в option compression; уровень 1–9 добавляется отдельно. |
SOAP_AUTHENTICATION_BASIC | 0 | HTTP auth | Basic/Digest authentication transport, не SOAP Header. |
SOAP_AUTHENTICATION_DIGEST | 1 | HTTP auth | Basic/Digest authentication transport, не SOAP Header. |
UNKNOWN_TYPE | 999998 | SOAP encoding | Низкоуровневый идентификатор типа encoded-модели. |
XSD_STRING | 101 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_BOOLEAN | 102 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_DECIMAL | 103 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_FLOAT | 104 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_DOUBLE | 105 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_DURATION | 106 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_DATETIME | 107 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_TIME | 108 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_DATE | 109 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_GYEARMONTH | 110 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_GYEAR | 111 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_GMONTHDAY | 112 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_GDAY | 113 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_GMONTH | 114 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_HEXBINARY | 115 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_BASE64BINARY | 116 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_ANYURI | 117 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_QNAME | 118 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_NOTATION | 119 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_NORMALIZEDSTRING | 120 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_TOKEN | 121 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_LANGUAGE | 122 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_NMTOKEN | 123 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_NAME | 124 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_NCNAME | 125 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_ID | 126 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_IDREF | 127 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_IDREFS | 128 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_ENTITY | 129 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_ENTITIES | 130 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_INTEGER | 131 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_NONPOSITIVEINTEGER | 132 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_NEGATIVEINTEGER | 133 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_LONG | 134 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_INT | 135 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_SHORT | 136 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_BYTE | 137 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_NONNEGATIVEINTEGER | 138 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_UNSIGNEDLONG | 139 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_UNSIGNEDINT | 140 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_UNSIGNEDSHORT | 141 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_UNSIGNEDBYTE | 142 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_POSITIVEINTEGER | 143 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_NMTOKENS | 144 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_ANYTYPE | 145 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_ANYXML | 147 | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
APACHE_MAP | 200 | SOAP encoding | Низкоуровневый идентификатор типа encoded-модели. |
SOAP_ENC_OBJECT | 301 | SOAP encoding | Низкоуровневый идентификатор типа encoded-модели. |
SOAP_ENC_ARRAY | 300 | SOAP encoding | Низкоуровневый идентификатор типа encoded-модели. |
XSD_1999_TIMEINSTANT | 401 | Legacy XSD | Устаревший XML Schema 1999 namespace/type для совместимости старых сервисов. |
XSD_NAMESPACE | 'http://www.w3.org/2001/XMLSchema' | XSD type | Идентификатор XML Schema типа для SoapVar/serializer. |
XSD_1999_NAMESPACE | 'http://www.w3.org/1999/XMLSchema' | Legacy XSD | Устаревший XML Schema 1999 namespace/type для совместимости старых сервисов. |
SOAP_SINGLE_ELEMENT_ARRAYS | 1 | Features | Битовый feature flag SoapClient/SoapServer. |
SOAP_WAIT_ONE_WAY_CALLS | 2 | Features | Битовый feature flag SoapClient/SoapServer. |
SOAP_USE_XSI_ARRAY_TYPE | 4 | Features | Битовый feature flag SoapClient/SoapServer. |
WSDL_CACHE_NONE | 0 | WSDL cache | Стратегия none/disk/memory/both для разбора WSDL. |
WSDL_CACHE_DISK | 1 | WSDL cache | Стратегия none/disk/memory/both для разбора WSDL. |
WSDL_CACHE_MEMORY | 2 | WSDL cache | Стратегия none/disk/memory/both для разбора WSDL. |
WSDL_CACHE_BOTH | 3 | WSDL cache | Стратегия none/disk/memory/both для разбора WSDL. |
SOAP_SSL_METHOD_TLS | 0 | Legacy TLS | Константа deprecated option ssl_method; используйте stream_context/современный TLS. |
SOAP_SSL_METHOD_SSLv2 | 1 | Legacy TLS | Константа deprecated option ssl_method; используйте stream_context/современный TLS. |
SOAP_SSL_METHOD_SSLv3 | 2 | Legacy TLS | Константа deprecated option ssl_method; используйте stream_context/современный TLS. |
SOAP_SSL_METHOD_SSLv23 | 3 | Legacy TLS | Константа deprecated option ssl_method; используйте stream_context/современный TLS. |
Полное дерево функций и методов официального book.soap
Это полный вызываемый API текущей официальной ветви: 31 страница. Дерево идёт по категориям и ведёт в карточки с сигнатурой, двумя выполненными сценариями, отказами и связанными операциями.
Две функции расширения
SoapClient — 14 методов
SoapClient::__callSoapClient::__constructSoapClient::__doRequestSoapClient::__getCookiesSoapClient::__getFunctionsSoapClient::__getLastRequestSoapClient::__getLastRequestHeadersSoapClient::__getLastResponseSoapClient::__getLastResponseHeadersSoapClient::__getTypesSoapClient::__setCookieSoapClient::__setLocationSoapClient::__setSoapHeadersSoapClient::__soapCall
SoapServer — 10 методов
SoapFault — 2 метода
SoapHeader / SoapParam / SoapVar
Как выбирать: новичок идёт по маршруту задачи в начале главы; опытный разработчик раскрывает это дерево и сразу переходит к карточке. Оба пути ведут к одному и тому же проверенному материалу.
SoapClient: договор, состояние, transport и диагностика
SoapClient — stateful adapter вокруг WSDL mapping, transport settings, cookies/default headers и последнего trace. Один настроенный объект уменьшает повтор настройки, но его состояние нельзя случайно делить между чужими пользователями.
- Конструктор загружает/кэширует WSDL и options.
- Вызов получает PHP args.
- Serializer создаёт XML.
- __doRequest выполняет transport.
- Decoder возвращает value/Fault.
- Cookie/trace state остаётся в объекте.
| Option | Что контролирует |
|---|---|
location | Endpoint URL; обязателен без WSDL, с WSDL переопределяет soap:address. |
uri | Target namespace; обязателен без WSDL, игнорируется WSDL-mode. |
style | SOAP_RPC или SOAP_DOCUMENT; в WSDL-mode берётся из binding. |
use | SOAP_ENCODED или SOAP_LITERAL; в WSDL-mode берётся из binding. |
soap_version | SOAP_1_1 по умолчанию либо SOAP_1_2. |
authentication | SOAP_AUTHENTICATION_BASIC или SOAP_AUTHENTICATION_DIGEST для HTTP auth. |
login | Username HTTP Basic/Digest. |
password | Password HTTP Basic/Digest; не путать с passphrase certificate. |
local_cert | PEM client certificate/private key для mutual TLS; файл защищают правами. |
passphrase | Passphrase private key из local_cert. |
proxy_host | Hostname HTTP proxy. |
proxy_port | TCP port proxy; нужен вместе с proxy_host. |
proxy_login | Username Basic auth на proxy. |
proxy_password | Password Basic auth на proxy. |
compression | ACCEPT + GZIP/DEFLATE + уровень 1–9. |
encoding | Внутренняя кодировка PHP values; wire request остаётся UTF-8. |
trace | Сохранять последний request/response и HTTP headers. |
classmap | WSDL type → fully-qualified PHP class; с PHP 8.4 доступна Clark notation. |
typemap | type_name/type_ns + from_xml/to_xml callbacks. |
exceptions | true бросает SoapFault, false возвращает SoapFault object. |
connection_timeout | Только connect timeout seconds; не общий deadline ответа. |
cache_wsdl | WSDL_CACHE_NONE/DISK/MEMORY/BOTH. |
user_agent | HTTP User-Agent интеграции. |
stream_context | TLS/HTTP context; не отключать verification как постоянное решение. |
features | Битовые SOAP_SINGLE_ELEMENT_ARRAYS/WAIT_ONE_WAY_CALLS/USE_XSI_ARRAY_TYPE. |
keep_alive | HTTP connection reuse; lifecycle клиента должен соответствовать worker/очереди. |
ssl_method | Deprecated с PHP 8.1; SOAP_SSL_METHOD_TLS не влияет на выбор протокола с PHP 7.2. Применять современную TLS настройку stream_context. |
Все private properties из официального synopsis PHP 8.5.11
Это видимое описание внутреннего состояния, а не разрешение читать свойства: они private и могут меняться. Public API приведён выше.
| Property из synopsis | Visibility | Тип 8.5.11 | Default | Внутренняя роль | История |
|---|---|---|---|---|---|
$uri | private | ?string | null | contract/mapping | Без отдельной записи changelog в frozen class page. |
$style | private | ?int | null | contract/mapping | Без отдельной записи changelog в frozen class page. |
$use | private | ?int | null | contract/mapping | Без отдельной записи changelog в frozen class page. |
$location | private | ?string | null | contract/mapping | Без отдельной записи changelog в frozen class page. |
$trace | private | bool | false | internal state | Без отдельной записи changelog в frozen class page. |
$compression | private | ?int | null | transport/TLS/proxy | Без отдельной записи changelog в frozen class page. |
$sdl | private | ?Soap\Sdl | null | contract/mapping | PHP 8.4: Soap\Sdl object заменил внутренний resource. |
$typemap | private | ?array | null | contract/mapping | PHP 8.4: array; раньше внутренний resource. |
$httpsocket | private | resource|mixed | null | transport/TLS/proxy | Без отдельной записи changelog в frozen class page. |
$httpurl | private | ?Soap\Url | null | transport/TLS/proxy | PHP 8.4: Soap\Url object заменил внутренний resource. |
$_login | private | ?string | null | HTTP auth | Без отдельной записи changelog в frozen class page. |
$_password | private | ?string | null | HTTP auth | Без отдельной записи changelog в frozen class page. |
$_use_digest | private | bool | false | HTTP auth | Без отдельной записи changelog в frozen class page. |
$_digest | private | ?string | null | HTTP auth | Без отдельной записи changelog в frozen class page. |
$_proxy_host | private | ?string | null | transport/TLS/proxy | Без отдельной записи changelog в frozen class page. |
$_proxy_port | private | ?int | null | transport/TLS/proxy | Без отдельной записи changelog в frozen class page. |
$_proxy_login | private | ?string | null | transport/TLS/proxy | Без отдельной записи changelog в frozen class page. |
$_proxy_password | private | ?string | null | transport/TLS/proxy | Без отдельной записи changelog в frozen class page. |
$_exceptions | private | bool | true | fault/trace | Без отдельной записи changelog в frozen class page. |
$_encoding | private | ?string | null | contract/mapping | Без отдельной записи changelog в frozen class page. |
$_classmap | private | ?array | null | contract/mapping | Без отдельной записи changelog в frozen class page. |
$_features | private | ?int | null | contract/mapping | Без отдельной записи changelog в frozen class page. |
$_connection_timeout | private | int | 0 | transport/TLS/proxy | Без отдельной записи changelog в frozen class page. |
$_stream_context | private | resource|mixed | null | transport/TLS/proxy | Без отдельной записи changelog в frozen class page. |
$_user_agent | private | ?string | null | transport/TLS/proxy | Без отдельной записи changelog в frozen class page. |
$_keep_alive | private | bool | true | transport/TLS/proxy | Без отдельной записи changelog в frozen class page. |
$_ssl_method | private | ?int | null | transport/TLS/proxy | Без отдельной записи changelog в frozen class page. |
$_soap_version | private | int | Нет class default; значение устанавливает конструктор/runtime. | contract/mapping | Без отдельной записи changelog в frozen class page. |
$_use_proxy | private | ?int | null | transport/TLS/proxy | Без отдельной записи changelog в frozen class page. |
$_cookies | private | array | [] | cookies/default headers | Без отдельной записи changelog в frozen class page. |
$__default_headers | private | ?array | null | cookies/default headers | Без отдельной записи changelog в frozen class page. |
$__soap_fault | private | ?SoapFault | null | fault/trace | Без отдельной записи changelog в frozen class page. |
$__last_request | private | ?string | null | fault/trace | Без отдельной записи changelog в frozen class page. |
$__last_response | private | ?string | null | fault/trace | Без отдельной записи changelog в frozen class page. |
$__last_request_headers | private | ?string | null | fault/trace | Без отдельной записи changelog в frozen class page. |
$__last_response_headers | private | ?string | null | fault/trace | Без отдельной записи changelog в frozen class page. |
Основные карточки: SoapClient::__construct, SoapClient::__soapCall, SoapClient::__getLastRequest, SoapClient::__doRequest.
SoapServer: узкий endpoint вместо файла со случайно экспортированными функциями
SoapServer — dispatcher: он не содержит бизнес-логику магазина, а связывает Envelope с узким набором PHP handlers. Полезный выигрыш — единая сериализация/fault contract и явная поверхность операций.
| Модель handler | Когда выбирать | Граница |
|---|---|---|
SoapServer::addFunction | Несколько маленьких stateless операций. | Только явный allowlist; не SOAP_FUNCTIONS_ALL. |
SoapServer::setClass | Связанные методы и создаваемый handler. | Публичные методы; constructor args; optional session persistence. |
SoapServer::setObject | Уже собранный object/dependencies/test double. | State текущего process/request; session persistence не обещана. |
- HTTP route не печатает лишний output.
- handle разбирает Envelope.
- Registry выбирает handler.
- Return/Header/Fault сериализуются.
- HTTP layer пишет status/headers/log.
Private property из официального synopsis
| Property из synopsis | Visibility | Тип 8.5.11 | Default | Внутренняя роль | История |
|---|---|---|---|---|---|
$__soap_fault | private | ?SoapFault | null | fault/trace | Без отдельной записи changelog в frozen class page. |
SoapFault: машинный код, безопасное сообщение и отдельный внутренний лог
SoapFault одновременно является SOAP-структурой и PHP Exception. Это мост между remote fault contract и локальным try/catch, но поля надо переводить в политику приложения осознанно.
| Свойство | Visibility | Тип 8.5.11 | Default | Назначение | История |
|---|---|---|---|---|---|
$faultstring | public | string | Нет class default; значение устанавливает конструктор/runtime. | Человекочитаемое SOAP fault message. | Без отдельной записи changelog в frozen class page. |
$faultcode | public | ?string | null | Машинный code/local name либо null. | Без отдельной записи changelog в frozen class page. |
$faultcodens | public | ?string | null | Namespace URI fault code, если code задан QName-массивом. | Без отдельной записи changelog в frozen class page. |
$faultactor | public | ?string | null | URI actor/node, сообщившего ошибку. | Без отдельной записи changelog в frozen class page. |
$detail | public | mixed | null | Дополнительные структурированные детали Fault. | Без отдельной записи changelog в frozen class page. |
$_name | public | ?string | null | Имя WSDL fault binding, если оно выбрано. | Без отдельной записи changelog в frozen class page. |
$headerfault | public | mixed | null | Данные Fault, относящиеся к SOAP Header. | Без отдельной записи changelog в frozen class page. |
$lang | public | string | '' | Язык SOAP 1.2 reason; exact PHP 8.5.11 caveat разобран в карточке конструктора. | Свойство добавлено в PHP 8.5. |
Унаследованный API Exception
Поскольку SoapFault extends Exception, у него есть protected свойства $message (default ""), $code (default 0), $file (default "") и $line (default 0). Их не читают напрямую снаружи: используют final public методы getMessage(), getCode(), getFile(), getLine(), getTrace(), getTraceAsString() и getPrevious(). SoapFault::__toString() переопределяет строковое представление Fault. Visibility и default здесь важны: они объясняют, почему $fault->message не является корректным внешним контрактом.
| Слой | Реакция |
|---|---|
| Неверные данные запроса | Client/Sender/domain fault; не повторять без исправления. |
| Временная зависимость | Server/Receiver; retry только если операция idempotent и есть bounded backoff. |
| Auth/permission | Не печатать credentials; различать HTTP auth и SOAP business fault. |
| Parser/WSDL mismatch | Проверить contract/cache/imports и фактический XML. |
Карточки: SoapFault::__construct, SoapFault::__toString, is_soap_fault.
SoapHeader: бизнес-метаданные внутри Envelope, а не HTTP-заголовок
SOAP Header находится внутри XML Envelope. HTTP Header находится перед body. Одинаковое слово «header» не делает их одним механизмом: Basic auth/User-Agent/Cookie живут в HTTP, Credentials/RequestId по SOAP-договору — в Envelope.
| Свойство | Visibility | Тип 8.5.11 | Default | Назначение | История |
|---|---|---|---|---|---|
$namespace | public | string | Нет class default; значение устанавливает конструктор/runtime. | URI namespace элемента Header. | Без отдельной записи changelog в frozen class page. |
$name | public | string | Нет class default; значение устанавливает конструктор/runtime. | Local name элемента Header. | Без отдельной записи changelog в frozen class page. |
$data | public | mixed | null | PHP-значение/SoapVar для содержимого элемента. | Без отдельной записи changelog в frozen class page. |
$mustUnderstand | public | bool | Нет class default; значение устанавливает конструктор/runtime. | Требование обязательной обработки получателем. | Без отдельной записи changelog в frozen class page. |
$actor | public | string|int|null | Нет class default; значение устанавливает конструктор/runtime. | Роль/actor, для которой предназначен Header. | Без отдельной записи changelog в frozen class page. |
- namespace URI + name задают смысл элемента.
- data превращается в дочерние узлы/значение.
- Serializer сам выбирает префикс.
- mustUnderstand/actor задают обязательность и роль.
Создание: SoapHeader::__construct; клиент: SoapClient::__setSoapHeaders; сервер: SoapServer::addSoapHeader.
SoapParam: имя аргумента для serializer, особенно без WSDL
В non-WSDL mode обычное значение может получить имя param0, которое не узнает сервис. SoapParam явно говорит serializer: значение 731 относится к аргументу orderId.
| Свойство | Visibility | Тип 8.5.11 | Default | Назначение | История |
|---|---|---|---|---|---|
$param_name | public | string | Нет class default; значение устанавливает конструктор/runtime. | Имя аргумента операции в XML. | Без отдельной записи changelog в frozen class page. |
$param_data | public | mixed | Нет class default; значение устанавливает конструктор/runtime. | PHP-значение аргумента. | Без отдельной записи changelog в frozen class page. |
- PHP value 731.
- SoapParam(data=731, name=orderId).
- XML
731 . - Удалённый handler сопоставляет имя.
Подробный выполненный пример: SoapParam::__construct. В WSDL-mode сначала доверяйте корректному контракту; ручная обёртка не лечит неверную wrapper structure.
SoapVar: значение с явным XSD-типом, именем и namespace
SoapVar нужен, когда одного PHP-типа мало: бинарная строка должна стать xsd:base64Binary, DateTime — xsd:dateTime, объект — конкретным QName. Он хранит value плюс metadata сериализации.
| Свойство | Visibility | Тип 8.5.11 | Default | Назначение | История |
|---|---|---|---|---|---|
$enc_type | public | int | Нет class default; значение устанавливает конструктор/runtime. | Numeric XSD_/SOAP_ENC_ encoding id. | Без отдельной записи changelog в frozen class page. |
$enc_value | public | mixed | null | Исходное PHP-значение. | Без отдельной записи changelog в frozen class page. |
$enc_stype | public | ?string | null | Явное имя XSD-типа либо null. | Без отдельной записи changelog в frozen class page. |
$enc_ns | public | ?string | null | Namespace URI явного XSD-типа. | Без отдельной записи changelog в frozen class page. |
$enc_name | public | ?string | null | Local name XML-узла. | Без отдельной записи changelog в frozen class page. |
$enc_namens | public | ?string | null | Namespace URI XML-узла. | Без отдельной записи changelog в frozen class page. |
- PHP value/bytes/object.
- encoding выбирает XSD_/SOAP_ENC_.
- type/name namespaces задают QName.
- Serializer создаёт lexical XML form.
Карточка с dateTime и binary: SoapVar::__construct.
Soap\Sdl: непрозрачное внутреннее представление WSDL с PHP 8.4
Soap\Sdl — final fully opaque class, которая с PHP 8.4 заменила внутренний resource soap_sdl. У неё нет публичного конструктора, методов и свойств для прикладного кода.
| Можно | Нельзя/не следует |
|---|---|
| Увидеть тип через Reflection/внутреннее состояние SoapClient. | Создавать напрямую или читать разобранный WSDL через private internals. |
| Учитывать при диагностике type changes PHP 8.4. | Сериализовать/хранить как свой domain object. |
| Использовать public __getFunctions/__getTypes. | Полагаться на layout opaque object между версиями. |
Практический public API для этой задачи: SoapClient::__getFunctions и SoapClient::__getTypes.
Soap\Url: непрозрачный transport URL object с PHP 8.4
Soap\Url — final fully opaque class, которая с PHP 8.4 заменила внутренний resource soap_url. Она обслуживает внутренний URL state transport и не является альтернативой parse_url/URI API приложения.
| Практическая задача | Public путь |
|---|---|
| Задать endpoint | SoapClient::__construct option location или SoapClient::__setLocation |
| Переопределить endpoint одного call | SoapClient::__soapCall option location |
| Особо разобрать redirect URI в PHP 8.5 | SoapClient::__doRequest параметр uriParserClass |
| Защититься от SSRF | Allowlist scheme/host/port до передачи URL; opaque class этого не делает. |
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
is_soap_faultПроверяет, является ли результат объектом SoapFault; нужен прежде всего для режима клиента <code>exceptions=false</code>.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
function is_soap_fault(mixed $object): boolПроверяет, является ли результат объектом SoapFault; нужен прежде всего для режима клиента exceptions=false.
Функция и документированная запись. function is_soap_fault(mixed $object): bool. Reflection PHP 8.5.11: is_soap_fault(mixed $object): bool. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
mixed $object | Проверяемое значение либо конкретный объект-обработчик — смысл зависит от операции; тип указан в сигнатуре. |
Возврат и договор. Возвращает true только для SoapFault, иначе false. Значение не меняется.
Отказ. Сама функция не делает HTTP-запрос и не выбрасывает Fault. Ошибка возникает раньше, при SOAP-вызове; при exceptions=true нужен catch (SoapFault $fault).
- Код получает результат SOAP-вызова.
- PHP проверяет класс объекта.
- Ветка ошибки читает faultcode/faultstring, успешная — полезные данные.
<?php
declare(strict_types=1);
$ok = (object) ['status' => 'paid'];
$fault = new SoapFault('Server', 'Склад временно недоступен');
echo is_soap_fault($ok) ? "fault\n" : "result\n";
echo is_soap_fault($fault) ? "fault\n" : "result\n";
Ожидаемый результат
result
fault
Проверка не анализирует строку и не считает любой Exception SOAP-ошибкой: она отвечает, является ли значение именно SoapFault. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(
manualSoapFault('Server', 'Товар не найден'),
null,
['exceptions' => false],
);
$result = $client->__soapCall('findProduct', [['sku' => 'NO-404']]);
if (is_soap_fault($result)) {
echo "fault: {$result->faultstring}\n";
} else {
echo "product received\n";
}
Ожидаемый результат
fault: Товар не найден
При exceptions=false не сработает catch: Fault приходит как возвращаемый объект, поэтому проверка должна стоять сразу после вызова. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Не смешивайте два режима обработки: либо exceptions=true и catch, либо exceptions=false и обязательный is_soap_fault после каждого вызова. Молчаливое чтение результата без проверки превращает faultstring в «данные».
Связанные операции: SoapFault::__construct, SoapClient::__soapCall.
use_soap_error_handlerПереключает специальный обработчик ошибок SoapServer и возвращает его прежнее состояние.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
function use_soap_error_handler(bool $enable = true): boolПереключает специальный обработчик ошибок SoapServer и возвращает его прежнее состояние.
Функция и документированная запись. function use_soap_error_handler(bool $enable = true): bool. Reflection PHP 8.5.11: use_soap_error_handler(bool $enable = true): bool. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
bool $enable = true | true включает преобразование PHP-ошибок обработчика в SOAP Fault, false возвращает обычный PHP error handler. |
Возврат и договор. Возвращает прежнее булево состояние. true позволяет SoapServer оформить PHP-ошибку как SOAP Fault; это не заменяет логирование и безопасную политику send_errors.
Отказ. Неверный тип аргумента даёт TypeError. Ошибка вне обработки SoapServer не превращается этой функцией в SOAP-ответ.
- Приложение сохраняет прежний режим.
- SoapServer выполняет обработчик запроса.
- PHP-ошибка превращается в Fault либо идёт обычному PHP handler.
- После ограниченного участка режим восстанавливают.
<?php
declare(strict_types=1);
$initial = use_soap_error_handler(false);
$previous = use_soap_error_handler(true);
echo $previous === false ? "до включения: обычный handler\n" : "unexpected\n";
use_soap_error_handler($initial);
echo "настройка восстановлена\n";
Ожидаемый результат
до включения: обычный handler
настройка восстановлена
Функция возвращает прошлое значение, поэтому библиотека может аккуратно восстановить окружение после локального опыта или теста. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
function loadWarehouse(): string
{
missing_inventory_driver(); // намеренная ошибка учебного обработчика
return 'never';
}
use_soap_error_handler(true);
$server = new SoapServer(null, ['uri' => 'urn:manual', 'send_errors' => false]);
$server->addFunction('loadWarehouse');
$xml = manualHandle($server, manualSoapRequest('loadWarehouse', []));
echo manualXmlValue($xml, 'faultstring'), "\n";
Ожидаемый результат
Internal Error
SOAP handler превращает фатальную ошибку в корректный Envelope. send_errors=false не выдаёт клиенту имя внутренней функции; подробности пишут в закрытый журнал процесса. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. В production не включайте выдачу внутренних сообщений только ради диагностики. Сочетайте SOAP Fault для клиента с серверным журналом и correlation id.
Связанные операции: SoapServer::handle, SoapServer::fault.
SoapFault::__constructСоздаёт стандартную SOAP-ошибку для ответа сервера или локального представления fault от клиента.
PHP 5+; параметр $lang добавлен в PHP 8.5 · soap; XML/libxml; HTTP transport for real remote calls
SoapFault::__construct( array|string|null $code, string $string, ?string $actor = null, mixed $details = null, ?string $name = null, mixed $headerFault = null, string $lang = "" )Создаёт стандартную SOAP-ошибку для ответа сервера или локального представления fault от клиента.
Метод и документированная запись. SoapFault::__construct( array|string|null $code, string $string, ?string $actor = null, mixed $details = null, ?string $name = null, mixed $headerFault = null, string $lang = "" ). Reflection PHP 8.5.11: SoapFault::__construct(array|string|null $code, string $string, ?string $actor = null, mixed $details = null, ?string $name = null, mixed $headerFault = null, string $lang = ""). Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
array|string|null $code | SOAP fault code. Для SOAP 1.1 обычно Client/Server, для SOAP 1.2 — соответствующий QName/код договора. |
string $string | Безопасное клиентское описание ошибки без трассировки, SQL и секретов. |
?string $actor = null | URI участника/роли, который создал или должен обработать header/fault; null/пустая строка оставляют значение неуказанным. |
mixed $details = null | Структурированные дополнительные сведения Fault; не включайте внутренние секреты и stack trace. |
?string $name = null | Имя удалённой операции, cookie, fault binding или XML-узла — точный смысл задаёт текущий метод. |
mixed $headerFault = null | Данные ошибки SOAP Header при специальном WSDL-контракте. |
string $lang = '' | Язык текста Fault для SOAP 1.2, например ru; параметр добавлен в PHP 8.5. |
Возврат и договор. Создаёт объект SoapFault; конструктор ничего не отправляет. Публичные поля faultcode, faultstring, faultactor, detail, headerfault и lang доступны после создания.
Отказ. Неверные PHP-типы дают TypeError. Пустой строковый code либо QName-массив не ровно из двух строк [namespace, localCode] даёт ValueError «not a valid fault code». Секреты в details окажутся в XML-ответе, если сервер сериализует fault.
- Код выбирает машинный fault code.
- Добавляет безопасное сообщение и при необходимости detail.
- SoapServer сериализует объект либо приложение ловит его как Exception.
<?php
declare(strict_types=1);
$fault = new SoapFault(
['urn:shop', 'OrderRejected'],
'Order cannot be confirmed',
'urn:shop:checkout',
['orderId' => 731, 'reason' => 'stock'],
'OrderFault',
null,
'ru',
);
echo $fault->faultcode, "\n";
echo $fault->faultstring, "\n";
echo $fault->detail['orderId'], ' / ', $fault->lang, "\n";
Ожидаемый результат
OrderRejected
Order cannot be confirmed
731 / en
QName-код, понятное сообщение и structured detail отделяют машинный договор от текста. В PHP 8.5.11 аргумент lang у прямого SoapFault::__construct разбирается, но exact source всё ещё записывает en; для реально сериализованного SOAP 1.2 Reason используйте проверенный SoapServer::fault и contract test. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
try {
throw new SoapFault('Client', 'Неверный код склада');
} catch (SoapFault $fault) {
echo "SOAP {$fault->faultcode}: {$fault->faultstring}\n";
echo "HTTP ответ приложения: 422\n";
}
try {
new SoapFault(['urn:shop'], 'Неполный QName');
} catch (ValueError $error) {
echo "invalid QName rejected\n";
}
Ожидаемый результат
SOAP Client: Неверный код склада
HTTP ответ приложения: 422
invalid QName rejected
SoapFault наследует Exception, поэтому участвует в обычном try/catch. QName-массив обязан состоять ровно из namespace URI и local code; неполный массив даёт ValueError. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. SOAP 1.1 и 1.2 по-разному задают допустимые коды/структуру. Сверяйте QName и WSDL fault; не используйте PHP exception message как публичный договор без фильтрации. На проверенном PHP 8.5.11 прямой конструктор пока сохраняет lang=en даже при другом седьмом аргументе — это зафиксированная runtime/source граница, а не обещание спецификации.
Связанные операции: SoapFault::__toString, SoapServer::fault, is_soap_fault.
SoapFault::__toStringВозвращает строковое представление SoapFault в формате исключения для диагностики разработчиком.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapFault::__toString(): stringВозвращает строковое представление SoapFault в формате исключения для диагностики разработчиком.
Метод и документированная запись. SoapFault::__toString(): string. Reflection PHP 8.5.11: SoapFault::__toString(): string. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
| Аргументов нет | Метод читает состояние клиента/сервера, созданное предыдущими вызовами. |
Возврат и договор. Возвращает строку с классом, сообщением, местом возникновения и stack trace. Формат предназначен для диагностики и не является стабильным API ответа.
Отказ. Метод не отправляет SOAP XML. Случайная публикация строки может раскрыть локальные пути и внутреннюю структуру приложения.
- PHP берёт поля у объекта Fault.
- Exception formatter добавляет файл, строку и trace.
- Разработчик пишет результат в закрытый лог либо извлекает стабильные поля отдельно.
<?php
declare(strict_types=1);
$fault = new SoapFault('Server', 'Сервис доставки не ответил');
$text = (string) $fault;
echo str_contains($text, 'SoapFault') ? "class present\n" : "class missing\n";
echo str_contains($text, 'Сервис доставки не ответил') ? "message present\n" : "message missing\n";
Ожидаемый результат
class present
message present
Полная строка похожа на строку Exception и содержит файл/trace, поэтому тест проверяет смысловые признаки, а не нестабильные номера строк. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
$fault = new SoapFault('Server', 'Timeout', 'urn:carrier', ['requestId' => 'req-42']);
$raw = $fault->__toString();
$requestId = is_array($fault->detail) ? ($fault->detail['requestId'] ?? '-') : '-';
printf("soap_fault code=%s actor=%s request=%s\n", $fault->faultcode, $fault->faultactor, $requestId);
echo str_contains($raw, 'SoapFault') && str_contains($raw, 'Timeout') ? "raw trace captured\n" : "raw trace missing\n";
Ожидаемый результат
soap_fault code=Server actor=urn:carrier request=req-42
raw trace captured
Пример действительно вызывает __toString(), но в стабильную строку журнала выводит отдельные поля. Полную трассировку сохраняют отдельно с контролем доступа. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Для машинной обработки читайте faultcode/faultstring/detail. Не сравнивайте полную строку в тестах и не отдавайте её посетителю.
Связанные операции: SoapFault::__construct.
SoapHeader::__constructСоздаёт типизированный элемент SOAP Header — например, credential, correlation id или контекст операции.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapHeader::__construct( string $namespace, string $name, mixed $data = ?, bool $mustunderstand = ?, string $actor = ? )Создаёт типизированный элемент SOAP Header — например, credential, correlation id или контекст операции.
Метод и документированная запись. SoapHeader::__construct( string $namespace, string $name, mixed $data = ?, bool $mustunderstand = ?, string $actor = ? ). Reflection PHP 8.5.11: SoapHeader::__construct(string $namespace, string $name, mixed $data /* optional; Reflection default unavailable */, bool $mustUnderstand = false, string|int|null $actor = null). Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
string $namespace | URI XML namespace бизнес-заголовка; это не произвольный префикс вроде ns1. |
string $name | Имя удалённой операции, cookie, fault binding или XML-узла — точный смысл задаёт текущий метод. |
mixed $data | PHP-значение для сериализации; форма должна соответствовать XSD/WSDL либо явной SoapVar. |
bool $mustUnderstand = false | Если true, получатель обязан понять заголовок или вернуть Fault. |
string|int|null $actor = null | URI участника/роли, который создал или должен обработать header/fault; null/пустая строка оставляют значение неуказанным. |
Возврат и договор. Создаёт SoapHeader с публичными полями namespace, name, data, mustUnderstand и actor. Сам по себе объект ещё не прикреплён к запросу/ответу.
Отказ. Пустые namespace или name дают ValueError. Строковый actor должен быть длиннее двух символов; integer actor допускает только SOAP_ACTOR_NEXT, SOAP_ACTOR_NONE или SOAP_ACTOR_UNLIMATERECEIVER, иначе ValueError. Неправильный, но непустой namespace обычно обнаружит уже удалённый сервис.
- Приложение знает namespace и имя из WSDL/спецификации.
- PHP сериализует data в дочерние XML-узлы.
- Клиент прикрепляет header через __setSoapHeaders/__soapCall, сервер — через addSoapHeader.
<?php
declare(strict_types=1);
$header = new SoapHeader(
'urn:shop:auth',
'Credentials',
['login' => 'robot-17', 'token' => 'demo-token'],
true,
SOAP_ACTOR_NEXT,
);
echo $header->namespace, "\n";
echo $header->name, ' / ', ($header->mustUnderstand ? 'required' : 'optional'), "\n";
try {
new SoapHeader('urn:shop:auth', 'Credentials', null, false, 999);
} catch (ValueError $error) {
echo "invalid actor rejected\n";
}
Ожидаемый результат
urn:shop:auth
Credentials / required
invalid actor rejected
Namespace — URI словаря сервиса, name — имя элемента, data — его содержимое. Integer actor разрешён только как SOAP_ACTOR_NEXT, SOAP_ACTOR_NONE или SOAP_ACTOR_UNLIMATERECEIVER. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '7'));
$client->__setSoapHeaders(new SoapHeader(
'urn:shop:auth',
'Credentials',
['login' => 'robot-17', 'token' => 'demo-token'],
));
$client->__soapCall('sum', [new SoapParam(3, 'a'), new SoapParam(4, 'b')]);
echo str_contains($client->seenRequest, '<SOAP-ENV:Header>') ? "header present\n" : "header missing\n";
echo str_contains($client->seenRequest, 'demo-token') ? "token present\n" : "token missing\n";
Ожидаемый результат
header present
token present
Trace/XML подтверждает фактическую сериализацию. В реальном журнале токен маскируют; здесь используется учебное значение. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Документированный synopsis и Reflection 8.5.11 расходятся в defaults/types optional-параметров: выше показаны обе записи. HTTP Authorization и SOAP Header — разные слои. Не используйте envelope namespace как namespace бизнес-заголовка.
Связанные операции: SoapClient::__setSoapHeaders, SoapServer::addSoapHeader, SoapVar::__construct.
SoapParam::__constructОборачивает значение с именем SOAP-параметра, чтобы non-WSDL вызов создал ожидаемый XML-узел.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapParam::__construct(mixed $data, string $name)Оборачивает значение с именем SOAP-параметра, чтобы non-WSDL вызов создал ожидаемый XML-узел.
Метод и документированная запись. SoapParam::__construct(mixed $data, string $name). Reflection PHP 8.5.11: SoapParam::__construct(mixed $data, string $name). Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
mixed $data | PHP-значение для сериализации; форма должна соответствовать XSD/WSDL либо явной SoapVar. |
string $name | Имя удалённой операции, cookie, fault binding или XML-узла — точный смысл задаёт текущий метод. |
Возврат и договор. Создаёт SoapParam с публичными param_name и param_data. Возвращаемого значения конструктора нет.
Отказ. Пустое имя даёт ValueError «must not be empty». Непустое, но неверное по договору имя сериализуется и обычно приводит к Fault удалённого сервиса. Тип значения всё ещё должен соответствовать XSD.
- Код берёт имя параметра из договора операции.
- SoapParam хранит имя и PHP-значение.
- SoapClient создаёт одноимённый XML-элемент при вызове.
<?php
declare(strict_types=1);
$parameter = new SoapParam(731, 'orderId');
echo $parameter->param_name, "\n";
echo $parameter->param_data, "\n";
try {
new SoapParam(731, '');
} catch (ValueError $error) {
echo "empty name rejected\n";
}
Ожидаемый результат
orderId
731
empty name rejected
Объект связывает PHP-значение 731 с именем orderId. Пустое имя отклоняет сам PHP с ValueError до сериализации. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '7'));
$result = $client->__soapCall('sum', [
new SoapParam(3, 'a'),
new SoapParam(4, 'b'),
]);
echo $result, "\n";
echo preg_match('/<a[^>]*>3<\/a>/', $client->seenRequest) ? "a named\n" : "a missing\n";
echo preg_match('/<b[^>]*>4<\/b>/', $client->seenRequest) ? "b named\n" : "b missing\n";
Ожидаемый результат
7
a named
b named
Это полезно в non-WSDL режиме, где клиент не может взять имена из контракта. В WSDL-mode обычно достаточно обычного массива, если WSDL корректен. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Не добавляйте SoapParam механически в WSDL-mode. Сначала посмотрите __getFunctions и фактический request trace; проблема может быть в структуре wrapper, а не в имени scalar.
Связанные операции: SoapClient::__soapCall, SoapVar::__construct.
SoapVar::__constructЯвно задаёт XSD/SOAP тип, имя и namespace значения, когда автоматическая сериализация не совпадает с контрактом.
PHP 5+; typeName/typeNamespace/nodeName/nodeNamespace nullable с PHP 8.0.3; DateTimeInterface для date/time исправлен в PHP 8.4 · soap; XML/libxml; HTTP transport for real remote calls
SoapVar::__construct( mixed $data, ?int $encoding, ?string $typeName = null, ?string $typeNamespace = null, ?string $nodeName = null, ?string $nodeNamespace = null )Явно задаёт XSD/SOAP тип, имя и namespace значения, когда автоматическая сериализация не совпадает с контрактом.
Метод и документированная запись. SoapVar::__construct( mixed $data, ?int $encoding, ?string $typeName = null, ?string $typeNamespace = null, ?string $nodeName = null, ?string $nodeNamespace = null ). Reflection PHP 8.5.11: SoapVar::__construct(mixed $data, ?int $encoding, ?string $typeName = null, ?string $typeNamespace = null, ?string $nodeName = null, ?string $nodeNamespace = null). Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
mixed $data | PHP-значение для сериализации; форма должна соответствовать XSD/WSDL либо явной SoapVar. |
?int $encoding | XSD_/SOAP_ENC_ идентификатор способа сериализации либо null для вывода типа по значению. |
?string $typeName = null | Имя XSD-типа из контракта, когда одного numeric encoding недостаточно. |
?string $typeNamespace = null | URI namespace указанного XSD-типа. |
?string $nodeName = null | Имя XML-элемента, которое должен получить сервис. |
?string $nodeNamespace = null | URI namespace XML-элемента. |
Возврат и договор. Создаёт SoapVar с enc_type, enc_value, enc_stype, enc_ns, enc_name и enc_namens. Реальный XML появляется только при сериализации клиентом/сервером.
Отказ. Numeric encoding, которого нет в таблице XSD_/SOAP_ENC_, даёт ValueError «not a valid encoding». Существующий encoding с неверным type/namespace может создать несовместимый XML и удалённый Fault.
- Приложение знает нужный XSD-тип и QName из WSDL.
- SoapVar связывает значение с метаданными сериализации.
- ext/soap создаёт XML lexical form и namespace узла.
<?php
declare(strict_types=1);
$date = new DateTimeImmutable('2026-10-15T12:30:00+03:00');
$value = new SoapVar($date, XSD_DATETIME, null, null, 'shippedAt', 'urn:shop');
echo $value->enc_type === XSD_DATETIME ? "xsd:dateTime\n" : "other\n";
echo $value->enc_name, ' / ', $value->enc_namens, "\n";
try {
new SoapVar('value', 999999);
} catch (ValueError $error) {
echo "unknown encoding rejected\n";
}
Ожидаемый результат
xsd:dateTime
shippedAt / urn:shop
unknown encoding rejected
С PHP 8.4 DateTimeInterface для xsd:dateTime сериализуется как ISO 8601. Неизвестный numeric encoding PHP отклоняет ValueError до сериализации. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('upload', 'string', 'accepted'));
$payload = new SoapVar("PDF\x00demo", XSD_BASE64BINARY, null, null, 'content', 'urn:files');
$result = $client->__soapCall('upload', [new SoapParam($payload, 'file')]);
echo $result, "\n";
echo str_contains($client->seenRequest, base64_encode("PDF\x00demo")) ? "base64 payload\n" : "payload missing\n";
Ожидаемый результат
accepted
base64 payload
SoapVar сообщает сериализатору XSD-тип; бинарные байты не вставляются в XML напрямую, а кодируются Base64. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. SoapVar — точечный инструмент для несовместимого контракта. Не заменяйте им чтение WSDL; для пользовательского XML безопаснее DOM/XMLWriter, а типы SOAP должны соответствовать XSD lexical rules.
Связанные операции: SoapParam::__construct, SoapHeader::__construct, SoapClient::__soapCall.
SoapClient::__constructСоздаёт клиент и фиксирует контракт, endpoint, transport, сериализацию, диагностику и политику ошибок будущих вызовов.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__construct(?string $wsdl, array $options = [])Создаёт клиент и фиксирует контракт, endpoint, transport, сериализацию, диагностику и политику ошибок будущих вызовов.
Метод и документированная запись. SoapClient::__construct(?string $wsdl, array $options = []). Reflection PHP 8.5.11: SoapClient::__construct(?string $wsdl, array $options = []). Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
?string $wsdl | URL или локальный путь к WSDL; null включает non-WSDL mode, где приложение само задаёт uri и endpoint. |
array $options = [] | Ассоциативный массив настроек. Допустимые ключи зависят от client/server и подробно разобраны в карточке конструктора. |
Возврат и договор. Конструктор создаёт объект или выбрасывает SoapFault, если WSDL нельзя загрузить/разобрать. В non-WSDL mode обязательны location и uri. Ключи options включают soap_version, style/use, login/password/authentication, local_cert/passphrase, proxy_*, compression, encoding, trace, classmap, typemap, exceptions, connection_timeout, cache_wsdl, user_agent, stream_context, features, keep_alive и deprecated ssl_method.
Отказ. Недоступный/невалидный WSDL даёт SoapFault. В non-WSDL mode отсутствие location или uri — фатальная ошибка конфигурации. connection_timeout ограничивает соединение, а не медленный ответ; для чтения действует default_socket_timeout/архитектурный deadline.
- PHP загружает и при необходимости кэширует WSDL либо принимает ручной договор.
- Создаёт внутренние mapping/transport settings.
- Последующие методы сериализуют аргументы согласно этому состоянию.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '9'));
$result = $client->__soapCall('sum', [new SoapParam(4, 'a'), new SoapParam(5, 'b')]);
echo $result, "\n";
echo $client->seenLocation, "\n";
Ожидаемый результат
9
http://local.invalid/soap
В non-WSDL mode приложение само задаёт location и uri. Mock заменяет только сеть; Envelope создаёт и разбирает настоящий ext/soap. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(
manualSoapResponse('sum', 'int', '15'),
__DIR__ . '/service.wsdl',
['cache_wsdl' => WSDL_CACHE_NONE],
);
echo $client->__getFunctions()[0], "\n";
echo $client->sum(7, 8), "\n";
Ожидаемый результат
int sum(int $a, int $b)
15
WSDL задаёт имя, типы, SOAPAction и endpoint. Cache отключён только в локальном изменяемом контракте; production WSDL обычно версионируют и кэшируют. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. WSDL может импортировать другие XSD/WSDL: доступны должны быть все зависимости. trace=true удерживает последний XML с возможными секретами. TLS verification не отключают ради «починить SOAP»; доверие настраивают CA/stream_context. В dev cache можно выключить, в production это цена повторного download/parse.
Связанные операции: SoapClient::__soapCall, SoapClient::__getFunctions, SoapClient::__getTypes.
SoapClient::__callMagic-dispatch неизвестного PHP-метода в SOAP-операцию; напрямую вызывать этот метод deprecated.
PHP 5+; прямой вызов deprecated в текущем руководстве · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__call(string $name, array $args): mixedMagic-dispatch неизвестного PHP-метода в SOAP-операцию; напрямую вызывать этот метод deprecated.
Метод и документированная запись. SoapClient::__call(string $name, array $args): mixed. Reflection PHP 8.5.11: SoapClient::__call(string $name, array $args): mixed. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
string $name | Имя удалённой операции, cookie, fault binding или XML-узла — точный смысл задаёт текущий метод. |
array $args | Аргументы операции. Для SOAP-вызова это упорядоченный/именованный массив; для setClass — variadic аргументы конструктора обработчика. |
Возврат и договор. Возвращает один scalar/object либо associative array нескольких output-параметров. При exceptions=false ошибка возвращается как SoapFault.
Отказ. При exceptions=true удалённый Fault/transport error выбрасывает SoapFault; при false возвращается объект Fault, который проверяют is_soap_fault.
- PHP не находит объявленный метод вроде sum.
- __call получает имя и аргументы.
- SoapClient строит Envelope, выполняет transport и декодирует ответ.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(
manualSoapResponse('sum', 'int', '12'),
__DIR__ . '/service.wsdl',
);
echo $client->sum(5, 7), "\n";
echo str_contains($client->seenAction, 'sum') ? "action: sum\n" : "action: other\n";
Ожидаемый результат
12
action: sum
Когда PHP не находит реальный метод sum, magic dispatch направляет вызов в SoapClient::__call. Такой синтаксис — обычный путь для WSDL-клиента. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '7'));
$old = $client->__call('sum', [new SoapParam(3, 'a'), new SoapParam(4, 'b')]);
$new = $client->__soapCall('sum', [new SoapParam(3, 'a'), new SoapParam(4, 'b')]);
echo 'direct: ', $old, "\n";
echo 'soapCall: ', $new, "\n";
Ожидаемый результат
direct: 7
soapCall: 7
Прямой вызов __call() документация помечает deprecated, хотя проверенный runtime 8.5.11 не обязан выдавать E_DEPRECATED. Результат показан рядом с явным __soapCall(); magic $client->sum() остаётся нормальным WSDL-синтаксисом. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Не пишите $client->__call(...) в новом коде. Для красивого WSDL-вызова используйте $client->Operation(); для per-call options/headers — __soapCall().
Связанные операции: SoapClient::__soapCall, is_soap_fault.
SoapClient::__soapCallНизкоуровневый вызов SOAP-операции с per-call endpoint/action/uri и входными/выходными SOAP headers.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__soapCall( string $name, array $args, ?array $options = null, SoapHeader|array|null $inputHeaders = null, array &$outputHeaders = null ): mixedНизкоуровневый вызов SOAP-операции с per-call endpoint/action/uri и входными/выходными SOAP headers.
Метод и документированная запись. SoapClient::__soapCall( string $name, array $args, ?array $options = null, SoapHeader|array|null $inputHeaders = null, array &$outputHeaders = null ): mixed. Reflection PHP 8.5.11: SoapClient::__soapCall(string $name, array $args, ?array $options = null, mixed $inputHeaders = null, mixed &$outputHeaders = null): mixed. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
string $name | Имя удалённой операции, cookie, fault binding или XML-узла — точный смысл задаёт текущий метод. |
array $args | Аргументы операции. Для SOAP-вызова это упорядоченный/именованный массив; для setClass — variadic аргументы конструктора обработчика. |
?array $options = null | Ассоциативный массив настроек. Допустимые ключи зависят от client/server и подробно разобраны в карточке конструктора. |
mixed $inputHeaders = null | Заголовок или массив заголовков только для текущего вызова. |
mixed &$outputHeaders = null | Выходной аргумент: после вызова PHP запишет сюда заголовки SOAP-ответа; переменную передают по ссылке. |
Возврат и договор. Если операция имеет один output, возвращается scalar/object; несколько именованных output-параметров дают ассоциативный массив. При exceptions=false отказ возвращается объектом SoapFault, который проверяют через is_soap_fault. $outputHeaders заполняется по ссылке и не является return value.
Отказ. С exceptions=true SOAP/transport fault бросается как SoapFault; с exceptions=false тот же отказ возвращается как SoapFault и не должен ошибочно считаться предметным результатом. Неверные parameter names/QName часто доходят до сервиса и возвращаются как Fault.
- Имя и args превращаются в Body.
- options уточняют transport/action текущего вызова.
- inputHeaders входят в Envelope Header.
- Ответ разбирается в return и outputHeaders.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '7'));
$result = $client->__soapCall(
'sum',
[new SoapParam(3, 'a'), new SoapParam(4, 'b')],
['location' => 'https://backup.example.test/soap', 'soapaction' => 'urn:manual#sum'],
);
echo $result, "\n";
echo $client->seenLocation, "\n";
Ожидаемый результат
7
https://backup.example.test/soap
Per-call location не меняет WSDL и удобен для управляемого failover. Endpoint всё равно берут из доверенной конфигурации, а не из пользовательского ввода. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$replyHeader = '<m:RequestId xmlns:m="urn:meta">req-42</m:RequestId>';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '7', $replyHeader));
$responseHeaders = [];
$result = $client->__soapCall(
'sum',
[new SoapParam(3, 'a'), new SoapParam(4, 'b')],
null,
new SoapHeader('urn:meta', 'ClientId', 'shop-1'),
$responseHeaders,
);
echo $result, "\n";
echo $responseHeaders['RequestId'], "\n";
Ожидаемый результат
7
req-42
Пятый аргумент — выходной: PHP заполняет переданную переменную. Это SOAP headers внутри Envelope, не HTTP response headers. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Не путайте массив аргументов операции с массивом одного wrapper-объекта: точную форму показывает WSDL и __getFunctions. Документация типизирует array &$outputHeaders = null, а Reflection PHP 8.5.11 оставляет inputHeaders/outputHeaders без runtime type; передавайте SoapHeader/массив и отдельную переменную по ссылке.
Связанные операции: SoapClient::__call, SoapParam::__construct, SoapHeader::__construct.
SoapClient::__doRequestВыполняет transport готового SOAP XML; переопределяется для тестов, очереди, наблюдаемости или особого протокола.
PHP 5+; $oneWay изменён с int на bool в PHP 8.0; $uriParserClass добавлен в PHP 8.5 · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__doRequest( string $request, string $location, string $action, int $version, bool $oneWay = false, ?string $uriParserClass = null ): ?stringВыполняет transport готового SOAP XML; переопределяется для тестов, очереди, наблюдаемости или особого протокола.
Метод и документированная запись. SoapClient::__doRequest( string $request, string $location, string $action, int $version, bool $oneWay = false, ?string $uriParserClass = null ): ?string. Reflection PHP 8.5.11: SoapClient::__doRequest(string $request, string $location, string $action, int $version, bool $oneWay = false, ?string $uriParserClass = null): ?string. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
string $request | Полный XML SOAP Envelope. В handle(null) сервер читает raw POST body; в тесте строку можно передать явно. |
string $location | Endpoint URL для HTTP-запроса; это адрес транспорта, а не target namespace. |
string $action | SOAPAction конкретной операции. Значение берут из WSDL/договора сервиса, не угадывают по имени PHP-метода. |
int $version | SOAP_1_1 или SOAP_1_2; версия определяет envelope namespace и HTTP media type. |
bool $oneWay = false | true, если договор не предусматривает предметный SOAP-ответ. Базовый transport после успешной отправки возвращает пустую строку, а при transport failure — null; внешний SOAP-вызов без SOAP_WAIT_ONE_WAY_CALLS не ждёт полезную нагрузку ответа. |
?string $uriParserClass = null | С PHP 8.5 имя класса разбора redirect URI; null оставляет стандартный разбор на основе parse_url. |
Возврат и договор. При обычном вызове возвращает XML SOAP response или null при transport failure. При base one-way transport успешная отправка возвращает пустую строку, отказ — null. Feature SOAP_WAIT_ONE_WAY_CALLS заставляет ждать response и снимает one-way поведение. В PHP 8.5 добавлен $uriParserClass.
Отказ. Base transport возвращает null при неуспешном HTTP transport; внешний SOAP-вызов затем применяет exceptions policy. Некорректный response XML ломает разбор после возврата. One-way не доказывает бизнес-доставку.
- Serializer строит request XML.
- __doRequest получает endpoint/action/version.
- Transport возвращает response XML.
- SoapClient декодирует его в PHP-значение.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '7'));
echo $client->__soapCall('sum', [new SoapParam(3, 'a'), new SoapParam(4, 'b')]), "\n";
printf("version=%d action=%s\n", $client->seenVersion, $client->seenAction);
echo str_contains($client->seenRequest, '<a xsi:type="xsd:int">3</a>') ? "body checked\n" : "body differs\n";
Ожидаемый результат
7
version=1 action=urn:manual#sum
body checked
Переопределение получает уже готовый Envelope и transport metadata. Это точка для test double, очереди или нестандартного транспорта, но не повод переписывать XML строковыми заменами. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
$url = getenv('SOAP_TEST_URL') ?: throw new RuntimeException('SOAP_TEST_URL missing');
$request = '<?xml version="1.0"?>'
. '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">'
. '<SOAP-ENV:Body><m:sum xmlns:m="urn:manual"><a>1</a><b>2</b></m:sum></SOAP-ENV:Body>'
. '</SOAP-ENV:Envelope>';
$client = new SoapClient(null, ['location' => $url, 'uri' => 'urn:manual', 'exceptions' => false]);
$success = $client->__doRequest($request, $url, 'urn:manual#sum', SOAP_1_1, true);
echo $success === '' ? "success: empty string\n" : "success: unexpected\n";
$failure = $client->__doRequest($request, 'http://127.0.0.1:1/unavailable', 'urn:manual#sum', SOAP_1_1, true);
echo $failure === null ? "failure: null\n" : "failure: unexpected\n";
Ожидаемый результат
success: empty string
failure: null
Base transport PHP 8.5.11 при oneWay=true возвращает пустую строку после успешной отправки и null при transport failure. Это не подтверждение обработки бизнес-события. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; HTTP endpoint — одноразовый loopback-сервер, без внешней сети.
Тонкости. Не логируйте сырой request без маскирования SOAP Header. При override сохраняйте сигнатуру, timeout/TLS policy и возвращайте полный Envelope. Редиректы и SSRF требуют allowlist endpoint.
Связанные операции: SoapClient::__getLastRequest, SoapClient::__getLastResponse.
SoapClient::__getCookiesВозвращает текущий cookie jar SoapClient для диагностики stateful SOAP/HTTP взаимодействия.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__getCookies(): arrayВозвращает текущий cookie jar SoapClient для диагностики stateful SOAP/HTTP взаимодействия.
Метод и документированная запись. SoapClient::__getCookies(): array. Reflection PHP 8.5.11: SoapClient::__getCookies(): array. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
| Аргументов нет | Метод читает состояние клиента/сервера, созданное предыдущими вызовами. |
Возврат и договор. Возвращает массив cookie; каждое имя указывает на массив значения и возможных атрибутов. Пустой jar — пустой массив.
Отказ. Метод не проверяет срок/пригодность cookie у удалённого сервиса. Секрет в debug output становится утечкой.
- Set-Cookie ответа или __setCookie меняет jar.
- Метод возвращает снимок состояния.
- Следующий HTTP-вызов применяет подходящие cookie.
<?php
declare(strict_types=1);
$client = new SoapClient(null, ['location' => 'http://local.invalid', 'uri' => 'urn:manual']);
$client->__setCookie('manual_session', 'abc');
$client->__setCookie('region', 'msk');
$client->__setCookie('region');
$cookies = $client->__getCookies();
echo $cookies['manual_session'][0], "\n";
echo array_key_exists('region', $cookies) ? "region kept\n" : "region removed\n";
Ожидаемый результат
abc
region removed
Cookie jar хранит дополнительные атрибуты массивом. Не предполагайте, что значение всегда лежит прямо по ключу без вложенности. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
$url = getenv('SOAP_TEST_URL') ?: throw new RuntimeException('SOAP_TEST_URL missing');
$client = new SoapClient(null, ['location' => $url, 'uri' => 'urn:manual']);
$client->__setCookie('manual_session', 'cart-731');
echo $client->__soapCall('readManualCookie', []), "\n";
echo $client->__getCookies()['manual_session'][0], "\n";
Ожидаемый результат
cart-731
cart-731
Здесь cookie прошёл через настоящий HTTP loopback. Для удалённого сервиса помните про область домена/path/secure и не выводите session token. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; HTTP endpoint — одноразовый loopback-сервер, без внешней сети.
Тонкости. SoapClient — stateful объект: переиспользование переносит cookies между вызовами. Не делите один клиент между разными пользователями/тенантами без явной изоляции.
Связанные операции: SoapClient::__setCookie.
SoapClient::__getFunctionsВозвращает текстовые прототипы операций, разобранных из WSDL.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__getFunctions(): ?arrayВозвращает текстовые прототипы операций, разобранных из WSDL.
Метод и документированная запись. SoapClient::__getFunctions(): ?array. Reflection PHP 8.5.11: SoapClient::__getFunctions(): ?array. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
| Аргументов нет | Метод читает состояние клиента/сервера, созданное предыдущими вызовами. |
Возврат и договор. Возвращает array строк в WSDL-mode и null без WSDL. Строки предназначены для диагностики, не для eval/code generation.
Отказ. Пустой/устаревший список часто означает другой WSDL/cache, а не отсутствие endpoint. Ошибка разбора WSDL возникает в конструкторе.
- Конструктор разбирает WSDL portType/messages.
- Метод форматирует операции в PHP-подобные прототипы.
- Разработчик сверяет имя/типы перед вызовом.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '0'), __DIR__ . '/service.wsdl');
foreach ($client->__getFunctions() ?? [] as $signature) {
echo $signature, "\n";
}
Ожидаемый результат
int sum(int $a, int $b)
Список полезен для быстрой диагностики имени и порядка аргументов, но не заменяет документацию ограничений типов и предметных ошибок. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
$client = new SoapClient(null, ['location' => 'http://local.invalid', 'uri' => 'urn:manual']);
echo $client->__getFunctions() === null ? "no WSDL prototypes\n" : "prototypes found\n";
Ожидаемый результат
no WSDL prototypes
В non-WSDL mode PHP не может вывести список удалённых операций: договор должен храниться в спецификации приложения. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. После обновления контракта учитывайте WSDL cache. Один прототип не показывает facets, minOccurs/maxOccurs, namespaces и fault contract.
Связанные операции: SoapClient::__getTypes, SoapClient::__construct.
SoapClient::__getTypesВозвращает текстовые описания XSD complex/simple types, разобранных из WSDL.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__getTypes(): ?arrayВозвращает текстовые описания XSD complex/simple types, разобранных из WSDL.
Метод и документированная запись. SoapClient::__getTypes(): ?array. Reflection PHP 8.5.11: SoapClient::__getTypes(): ?array. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
| Аргументов нет | Метод читает состояние клиента/сервера, созданное предыдущими вызовами. |
Возврат и договор. Возвращает array строк в WSDL-mode и null в non-WSDL mode.
Отказ. Метод не валидирует ваши PHP DTO и не сообщает все XSD facets. Не загруженный import проявится ещё при создании клиента.
- WSDL импортирует XSD.
- Parser строит внутреннюю модель типов.
- Метод форматирует её в читаемые строки.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '0'), __DIR__ . '/service.wsdl');
$types = $client->__getTypes() ?? [];
echo str_contains($types[0], 'struct Order') ? "Order type\n" : "other type\n";
echo str_contains($types[0], 'string status') ? "status: string\n" : "status missing\n";
Ожидаемый результат
Order type
status: string
Тип помогает понять форму объекта ответа до var_dump реального заказа. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
$client = new SoapClient(null, ['location' => 'http://local.invalid', 'uri' => 'urn:manual']);
var_export($client->__getTypes());
echo "\n";
Ожидаемый результат
NULL
null — ожидаемая граница режима, а не сетевой сбой. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Classmap связывают с точным type name/namespace, а не с именем XML-элемента. Для одинаковых имён в разных namespace с PHP 8.4 доступна Clark notation.
Связанные операции: SoapClient::__getFunctions, SoapClient::__construct.
SoapClient::__getLastRequestВозвращает XML последнего SOAP request, если клиент создан с <code>trace=true</code>.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__getLastRequest(): ?stringВозвращает XML последнего SOAP request, если клиент создан с trace=true.
Метод и документированная запись. SoapClient::__getLastRequest(): ?string. Reflection PHP 8.5.11: SoapClient::__getLastRequest(): ?string. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
| Аргументов нет | Метод читает состояние клиента/сервера, созданное предыдущими вызовами. |
Возврат и договор. Возвращает строку XML либо null, когда request ещё не было или trace выключен.
Отказ. Это не повтор запроса и не доказательство доставки. XML может содержать пароль/token/персональные данные.
- Последний вызов создаёт Envelope.
- При trace=true клиент сохраняет копию.
- Метод отдаёт её для локальной диагностики.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '7'));
$client->__soapCall('sum', [new SoapParam(3, 'a'), new SoapParam(4, 'b')]);
$xml = $client->__getLastRequest();
echo is_string($xml) && str_contains($xml, '<ns1:sum>') ? "sum envelope\n" : "missing\n";
echo is_string($xml) && str_contains($xml, '>4</b>') ? "b=4\n" : "b missing\n";
Ожидаемый результат
sum envelope
b=4
Вместо угадывания структуры сравниваем фактический Envelope с документацией поставщика. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '3'), null, ['trace' => false]);
$client->__soapCall('sum', [new SoapParam(1, 'a'), new SoapParam(2, 'b')]);
echo $client->__getLastRequest() === null ? "trace is off\n" : "request retained\n";
Ожидаемый результат
trace is off
Transport был выполнен, но диагностическая копия не сохранена. Это отдельная настройка, а не ошибка вызова. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Маскируйте secrets до журнала и ограничивайте размер. Не включайте trace постоянно в высоконагруженном long-lived worker без необходимости.
Связанные операции: SoapClient::__getLastRequestHeaders, SoapClient::__getLastResponse.
SoapClient::__getLastResponseВозвращает XML последнего SOAP response при включённом trace.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__getLastResponse(): ?stringВозвращает XML последнего SOAP response при включённом trace.
Метод и документированная запись. SoapClient::__getLastResponse(): ?string. Reflection PHP 8.5.11: SoapClient::__getLastResponse(): ?string. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
| Аргументов нет | Метод читает состояние клиента/сервера, созданное предыдущими вызовами. |
Возврат и договор. Возвращает строку XML либо null. Декодированный return/Fault метод не заменяет.
Отказ. Ответ может быть большим и содержать персональные данные. Невалидный XML может вызвать Fault до полезной диагностики.
- Transport возвращает Envelope.
- Trace сохраняет raw response.
- Decoder строит PHP-результат отдельно.
- Разработчик сравнивает два слоя.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '7'));
$value = $client->__soapCall('sum', [new SoapParam(3, 'a'), new SoapParam(4, 'b')]);
$xml = $client->__getLastResponse();
echo $value, "\n";
echo is_string($xml) && str_contains($xml, '>7</return>') ? "raw return=7\n" : "raw missing\n";
Ожидаемый результат
7
raw return=7
Так находят границу: XML правильный, а PHP mapping неожиданен — значит исследуют WSDL/classmap/typemap, а не сеть. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapFault('Server', 'Stock unavailable'), null, ['exceptions' => false]);
$result = $client->__soapCall('reserve', [['sku' => 'A-1']]);
echo is_soap_fault($result) ? "fault object\n" : "result object\n";
echo str_contains((string) $client->__getLastResponse(), '<SOAP-ENV:Fault>') ? "fault XML\n" : "no fault XML\n";
Ожидаемый результат
fault object
fault XML
Raw XML помогает подтвердить, что Fault пришёл от transport double/сервиса; приложение всё равно работает со структурированным SoapFault. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Логируйте correlation id, timing и redacted fragment, а не полный ответ без ограничений. Binary base64 резко увеличивает размер trace.
Связанные операции: SoapClient::__getLastResponseHeaders, SoapClient::__getLastRequest.
SoapClient::__getLastRequestHeadersВозвращает HTTP-заголовки последнего SOAP request при <code>trace=true</code>.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__getLastRequestHeaders(): ?stringВозвращает HTTP-заголовки последнего SOAP request при trace=true.
Метод и документированная запись. SoapClient::__getLastRequestHeaders(): ?string. Reflection PHP 8.5.11: SoapClient::__getLastRequestHeaders(): ?string. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
| Аргументов нет | Метод читает состояние клиента/сервера, созданное предыдущими вызовами. |
Возврат и договор. Возвращает строку заголовков либо null. SOAP Envelope Header смотрят в __getLastRequest, это другой слой.
Отказ. Метод не доступен до реального HTTP transport и ничего не возвращает при trace=false. Заголовки могут содержать Authorization/Cookie.
- HTTP transport собирает request line/headers.
- Trace сохраняет текст.
- Метод отдаёт его для диагностики proxy/auth/content type/action.
<?php
declare(strict_types=1);
$url = getenv('SOAP_TEST_URL') ?: throw new RuntimeException('SOAP_TEST_URL missing');
$client = new SoapClient(null, ['location' => $url, 'uri' => 'urn:manual', 'trace' => true]);
$client->__soapCall('sum', [new SoapParam(2, 'a'), new SoapParam(3, 'b')]);
$headers = (string) $client->__getLastRequestHeaders();
echo str_starts_with($headers, 'POST ') ? "POST\n" : "method differs\n";
echo stripos($headers, 'Content-Type: text/xml') !== false ? "SOAP 1.1 content type\n" : "content type differs\n";
echo stripos($headers, 'SOAPAction:') !== false ? "SOAPAction present\n" : "SOAPAction missing\n";
Ожидаемый результат
POST
SOAP 1.1 content type
SOAPAction present
Выполняется настоящий HTTP-запрос к одноразовому loopback-серверу, поэтому заголовки созданы transport ext/soap. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; HTTP endpoint — одноразовый loopback-сервер, без внешней сети.
<?php
declare(strict_types=1);
$url = getenv('SOAP_TEST_URL') ?: throw new RuntimeException('SOAP_TEST_URL missing');
$client = new SoapClient(null, [
'location' => $url,
'uri' => 'urn:manual',
'trace' => true,
'user_agent' => 'ManualService/1.0',
]);
$client->__soapCall('greet', [new SoapParam('Анна', 'name')]);
$headers = (string) $client->__getLastRequestHeaders();
echo stripos($headers, 'User-Agent: ManualService/1.0') !== false ? "agent ok\n" : "agent missing\n";
Ожидаемый результат
agent ok
User-Agent помогает поставщику различать интеграции; он не должен содержать секреты или пользовательский ввод. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; HTTP endpoint — одноразовый loopback-сервер, без внешней сети.
Тонкости. Перед журналом удаляйте Authorization, Cookie и proxy credentials. Для SOAP 1.2 Content-Type/action устроены иначе, чем для SOAP 1.1.
Связанные операции: SoapClient::__getLastRequest, SoapClient::__getLastResponseHeaders.
SoapClient::__getLastResponseHeadersВозвращает HTTP response headers последнего SOAP transport при trace=true.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__getLastResponseHeaders(): ?stringВозвращает HTTP response headers последнего SOAP transport при trace=true.
Метод и документированная запись. SoapClient::__getLastResponseHeaders(): ?string. Reflection PHP 8.5.11: SoapClient::__getLastResponseHeaders(): ?string. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
| Аргументов нет | Метод читает состояние клиента/сервера, созданное предыдущими вызовами. |
Возврат и договор. Возвращает строку либо null. Заголовки SOAP Envelope получают пятым аргументом __soapCall, а не здесь.
Отказ. Промежуточный proxy может менять/добавлять заголовки. Наличие 200 не означает успешную предметную операцию.
- Endpoint отвечает status/headers/body.
- Transport сохраняет headers при trace.
- Decoder отдельно разбирает SOAP body.
<?php
declare(strict_types=1);
$url = getenv('SOAP_TEST_URL') ?: throw new RuntimeException('SOAP_TEST_URL missing');
$client = new SoapClient(null, ['location' => $url, 'uri' => 'urn:manual', 'trace' => true]);
$client->__soapCall('sum', [new SoapParam(2, 'a'), new SoapParam(3, 'b')]);
$headers = (string) $client->__getLastResponseHeaders();
echo str_contains($headers, '200 OK') ? "HTTP 200\n" : "status differs\n";
echo stripos($headers, 'X-Manual-Server: loopback') !== false ? "server marker\n" : "marker missing\n";
Ожидаемый результат
HTTP 200
server marker
HTTP status/header диагностируют gateway и transport; предметный SOAP Fault при этом способен прийти и с HTTP 200. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; HTTP endpoint — одноразовый loopback-сервер, без внешней сети.
<?php
declare(strict_types=1);
$base = getenv('SOAP_TEST_URL') ?: throw new RuntimeException('SOAP_TEST_URL missing');
$client = new SoapClient(null, [
'location' => $base . '?persistence=1',
'uri' => 'urn:manual',
'trace' => true,
]);
echo $client->__soapCall('increment', []), "\n";
$headers = (string) $client->__getLastResponseHeaders();
echo stripos($headers, 'Set-Cookie: PHPSESSID=') !== false ? "session issued\n" : "session missing\n";
Ожидаемый результат
1
session issued
Пример показывает transport state, необходимый SOAP_PERSISTENCE_SESSION. В production session cookie защищают Secure/HttpOnly/SameSite там, где это применимо. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; HTTP endpoint — одноразовый loopback-сервер, без внешней сети.
Тонкости. Смотрите HTTP status, Retry-After, Set-Cookie и correlation headers вместе с SoapFault. Маскируйте cookies и auth challenges в логах.
Связанные операции: SoapClient::__getLastResponse, SoapClient::__soapCall.
SoapClient::__setCookieДобавляет, обновляет или удаляет HTTP cookie для следующих вызовов этого SoapClient.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__setCookie(string $name, ?string $value = null): voidДобавляет, обновляет или удаляет HTTP cookie для следующих вызовов этого SoapClient.
Метод и документированная запись. SoapClient::__setCookie(string $name, ?string $value = null): void. Reflection PHP 8.5.11: SoapClient::__setCookie(string $name, ?string $value = null): void. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
string $name | Имя удалённой операции, cookie, fault binding или XML-узла — точный смысл задаёт текущий метод. |
?string $value = null | Значение cookie; null удаляет cookie из состояния клиента. |
Возврат и договор. Возвращаемого значения нет. Любая строка, включая пустую, сохраняется в jar; null или пропущенный второй аргумент удаляет cookie. Параметр value nullable с PHP 8.0.
Отказ. Неверный тип даёт TypeError. Сервер может игнорировать cookie из-за domain/path/secure policy или собственного договора.
- Приложение меняет cookie jar объекта.
- Следующий HTTP request получает Cookie header.
- Set-Cookie ответа может обновить jar снова.
<?php
declare(strict_types=1);
$client = new SoapClient(null, ['location' => 'http://local.invalid', 'uri' => 'urn:manual']);
$client->__setCookie('region', 'spb');
$client->__setCookie('region', 'msk');
echo $client->__getCookies()['region'][0], "\n";
$client->__setCookie('empty', '');
echo array_key_exists('empty', $client->__getCookies()) && $client->__getCookies()['empty'][0] === '' ? "empty string kept\n" : "empty string lost\n";
$client->__setCookie('region', null);
echo array_key_exists('region', $client->__getCookies()) ? "kept\n" : "deleted\n";
Ожидаемый результат
msk
empty string kept
deleted
Повторная установка меняет значение. Пустая строка — настоящее сохранённое значение; только null или пропущенный второй аргумент удаляет cookie. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
$url = getenv('SOAP_TEST_URL') ?: throw new RuntimeException('SOAP_TEST_URL missing');
$client = new SoapClient(null, ['location' => $url, 'uri' => 'urn:manual']);
$client->__setCookie('manual_session', 'request-42');
echo $client->__soapCall('readManualCookie', []), "\n";
Ожидаемый результат
request-42
Loopback-сервис читает обычный HTTP Cookie. Если договор требует SOAP Header, __setCookie — не тот инструмент. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; HTTP endpoint — одноразовый loopback-сервер, без внешней сети.
Тонкости. Пустая строка и отсутствие cookie — разные состояния. Не используйте cookie вместо SOAP Header/HTTP Authorization, если сервис требует другой механизм. Не переиспользуйте клиент с чужим session cookie.
Связанные операции: SoapClient::__getCookies.
SoapClient::__setLocationМеняет endpoint последующих вызовов и возвращает прежний override. <code>null</code> или пустая строка очищают override; endpoint из WSDL становится fallback только в WSDL-mode. У non-WSDL клиента после очистки нет endpoint до новой настройки.
PHP 5+; $location nullable с PHP 8.0.3 · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__setLocation(?string $location = null): ?stringМеняет endpoint последующих вызовов и возвращает прежний override. null или пустая строка очищают override; endpoint из WSDL становится fallback только в WSDL-mode. У non-WSDL клиента после очистки нет endpoint до новой настройки.
Метод и документированная запись. SoapClient::__setLocation(?string $location = null): ?string. Reflection PHP 8.5.11: SoapClient::__setLocation(?string $location = null): ?string. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
?string $location = null | Endpoint URL для HTTP-запроса; это адрес транспорта, а не target namespace. |
Возврат и договор. Возвращает прежний endpoint как string либо null. Изменяет состояние именно текущего клиента.
Отказ. Неверный/запрещённый URL проявится при следующем вызове. URL из пользовательского ввода создаёт SSRF-риск.
- Клиент хранит основной endpoint.
- Метод заменяет его и возвращает старый.
- Следующий transport использует новый адрес.
<?php
declare(strict_types=1);
$client = new SoapClient(null, ['location' => 'https://primary.example.test/soap', 'uri' => 'urn:manual']);
$old = $client->__setLocation('https://backup.example.test/soap');
echo "old: ", $old, "\n";
$beforeEmpty = $client->__setLocation('');
echo "empty cleared: ", $beforeEmpty, "\n";
echo $client->__setLocation('https://next.example.test/soap') === null ? "after empty: no override\n" : "after empty: override remained\n";
$beforeNull = $client->__setLocation(null);
echo "null cleared: ", $beforeNull, "\n";
echo $client->__setLocation('https://last.example.test/soap') === null ? "after null: no override\n" : "after null: override remained\n";
Ожидаемый результат
old: https://primary.example.test/soap
empty cleared: https://backup.example.test/soap
after empty: no override
null cleared: https://next.example.test/soap
after null: no override
И пустая строка, и null очищают location override. WSDL-клиент после очистки снова берёт endpoint из WSDL; у non-WSDL клиента fallback нет, поэтому до запроса нужно снова задать location или передать per-call option. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
$url = getenv('SOAP_TEST_URL') ?: throw new RuntimeException('SOAP_TEST_URL missing');
$client = new SoapClient(null, ['location' => 'http://127.0.0.1:1/unavailable', 'uri' => 'urn:manual']);
$previous = $client->__setLocation($url);
echo str_contains((string) $previous, ':1/') ? "old endpoint recorded\n" : "old endpoint differs\n";
echo $client->__soapCall('sum', [new SoapParam(8, 'a'), new SoapParam(9, 'b')]), "\n";
Ожидаемый результат
old endpoint recorded
17
Failover выполняется до запроса; не нужно ждать заведомо недоступный адрес в учебном опыте. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; HTTP endpoint — одноразовый loopback-сервер, без внешней сети.
Тонкости. Location nullable с PHP 8.0.3. Failover адреса задают allowlist/конфигурацией. Смена location не меняет target namespace, SOAPAction и XSD-контракт.
Связанные операции: SoapClient::__soapCall, SoapClient::__construct.
SoapClient::__setSoapHeadersЗадаёт default SOAP headers для всех последующих вызовов клиента либо очищает их.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapClient::__setSoapHeaders(SoapHeader|array|null $headers = null): boolЗадаёт default SOAP headers для всех последующих вызовов клиента либо очищает их.
Метод и документированная запись. SoapClient::__setSoapHeaders(SoapHeader|array|null $headers = null): bool. Reflection PHP 8.5.11: SoapClient::__setSoapHeaders(mixed $headers = null): bool. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
mixed $headers = null | Один SoapHeader, массив заголовков либо null для удаления ранее установленных. |
Возврат и договор. Возвращает bool успеха. Один SoapHeader или массив заменяет предыдущий набор; null удаляет его.
Отказ. Прямой аргумент другого типа (например string/stdClass) даёт TypeError. Массив принимается как container, но любой элемент не SoapHeader вызывает немедленный фатальный E_ERROR «Invalid SOAP header», который обычный try/catch не перехватывает. Семантически неверный namespace обычно обнаруживает удалённый сервис.
- Код создаёт типизированные SoapHeader.
- Метод сохраняет набор в состоянии клиента.
- Каждый следующий Envelope получает эти headers до замены/очистки.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '3'));
$client->__setSoapHeaders(new SoapHeader('urn:meta', 'RequestId', 'req-1'));
$client->__soapCall('sum', [new SoapParam(1, 'a'), new SoapParam(2, 'b')]);
echo str_contains($client->seenRequest, 'req-1') ? "header sent\n" : "missing\n";
$client->__setSoapHeaders(null);
$client->__soapCall('sum', [new SoapParam(1, 'a'), new SoapParam(2, 'b')]);
echo str_contains($client->seenRequest, 'req-1') ? "header kept\n" : "header cleared\n";
Ожидаемый результат
header sent
header cleared
Метод заменяет весь default header set. Null удаляет прежние значения для будущих вызовов. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/mock-soap.php';
$client = new ManualMockSoapClient(manualSoapResponse('sum', 'int', '3'));
$ok = $client->__setSoapHeaders([
new SoapHeader('urn:meta', 'RequestId', 'req-42'),
new SoapHeader('urn:meta', 'Locale', 'ru-RU'),
]);
$client->__soapCall('sum', [new SoapParam(1, 'a'), new SoapParam(2, 'b')]);
echo $ok ? "headers accepted\n" : "headers rejected\n";
echo str_contains($client->seenRequest, 'req-42') && str_contains($client->seenRequest, 'ru-RU') ? "both sent\n" : "missing value\n";
Ожидаемый результат
headers accepted
both sent
Массив нужен для нескольких sibling элементов Header, а не для произвольного вложенного XML. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Default header легко случайно перенести в другой вызов. Для одноразового значения используйте четвёртый аргумент __soapCall. Никогда не печатайте auth header в журнал без маскирования.
Связанные операции: SoapHeader::__construct, SoapClient::__soapCall.
SoapServer::__constructСоздаёт SOAP endpoint в WSDL или non-WSDL mode и задаёт политику сериализации/ошибок.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapServer::__construct(?string $wsdl, array $options = [])Создаёт SOAP endpoint в WSDL или non-WSDL mode и задаёт политику сериализации/ошибок.
Метод и документированная запись. SoapServer::__construct(?string $wsdl, array $options = []). Reflection PHP 8.5.11: SoapServer::__construct(?string $wsdl, array $options = []). Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
?string $wsdl | URL или локальный путь к WSDL; null включает non-WSDL mode, где приложение само задаёт uri и endpoint. |
array $options = [] | Ассоциативный массив настроек. Допустимые ключи зависят от client/server и подробно разобраны в карточке конструктора. |
Возврат и договор. Конструктор создаёт объект сервера. С WSDL он читает контракт; с null требует uri. Options включают soap_version, actor, encoding, classmap, typemap, cache_wsdl, features, send_errors и trace.
Отказ. Невалидный WSDL/option даёт SoapFault/Error до обработки request. send_errors=true способен раскрыть внутренние сообщения клиенту.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
function sum(int $a, int $b): int { return $a + $b; }
$server = new SoapServer(null, ['uri' => 'urn:manual']);
$server->addFunction('sum');
$response = manualHandle($server, manualSoapRequest('sum', ['a' => 6, 'b' => 7]));
echo manualXmlValue($response), "\n";
Ожидаемый результат
13
Non-WSDL серверу обязательно сообщают target namespace. Строка request передана явно, поэтому пример работает в CLI без HTTP. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
function sum(int $a, int $b): int { return $a + $b; }
$server = new SoapServer(__DIR__ . '/service.wsdl', ['cache_wsdl' => WSDL_CACHE_NONE]);
$server->addFunction('sum');
$response = manualHandle($server, manualSoapRequest('sum', ['a' => 10, 'b' => 5]));
echo manualXmlValue($response), "\n";
Ожидаемый результат
15
WSDL задаёт operation/messages/binding; PHP-функция реализует поведение. В production контракт версионируют и проверяют на совместимость до deploy. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. SoapServer не генерирует WSDL из PHP-кода. Server option classmap принимает WSDL type → PHP class; с PHP 8.4 ключ может использовать Clark notation {namespace}type для одинаковых имён из разных namespace. Отдельно проектируйте контракт, ограничения и faults.
Связанные операции: SoapServer::handle, SoapServer::addFunction, SoapServer::setClass.
SoapServer::addFunctionРегистрирует одну или несколько PHP-функций как доступные SOAP-операции.
PHP 5+; int/SOAP_FUNCTIONS_ALL deprecated с PHP 8.4 · soap; XML/libxml; HTTP transport for real remote calls
SoapServer::addFunction(array|string|int $functions): voidРегистрирует одну или несколько PHP-функций как доступные SOAP-операции.
Метод и документированная запись. SoapServer::addFunction(array|string|int $functions): void. Reflection PHP 8.5.11: SoapServer::addFunction(mixed $functions): void. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
mixed $functions | Имя функции или allowlist имён. Передача int/SOAP_FUNCTIONS_ALL deprecated с PHP 8.4 и опасна экспортом лишних функций. |
Возврат и договор. Возвращаемого значения нет. Принимает string или array имён; int/SOAP_FUNCTIONS_ALL ещё принимается, но deprecated с PHP 8.4.
Отказ. Несуществующее/неподходящее имя обнаруживается при регистрации или вызове. Экспорт всех функций раскрывает лишнюю поверхность и поэтому deprecated.
- Код составляет allowlist функций.
- SoapServer сохраняет registry.
- handle сопоставляет operation с разрешённой функцией.
<?php
declare(strict_types=1);
$server = new SoapServer(null, ['uri' => 'urn:manual']);
function quoteTotal(int $quantity, int $price): int { return $quantity * $price; }
$server->addFunction('quoteTotal');
echo implode(', ', $server->getFunctions()), "\n";
Ожидаемый результат
quoteTotal
Allowlist делает поверхность сервиса явной: локальные вспомогательные функции наружу не выходят. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
function reserveStock(string $sku): string { return 'reserved:' . $sku; }
function releaseStock(string $sku): string { return 'released:' . $sku; }
$server = new SoapServer(null, ['uri' => 'urn:manual']);
$server->addFunction(['reserveStock', 'releaseStock']);
$names = $server->getFunctions();
sort($names);
echo implode(' | ', $names), "\n";
Ожидаемый результат
releaseStock | reserveStock
С PHP 8.4 int/SOAP_FUNCTIONS_ALL deprecated: массив имён безопаснее и показывает намерение. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Сигнатура/порядок входов должны совпасть с WSDL. Output-параметры в PHP-функцию не передают; несколько выходов возвращают ассоциативным массивом имён.
Связанные операции: SoapServer::getFunctions, SoapServer::handle.
SoapServer::addSoapHeaderДобавляет SoapHeader к ответу, формируемому для текущего обрабатываемого запроса.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapServer::addSoapHeader(SoapHeader $header): voidДобавляет SoapHeader к ответу, формируемому для текущего обрабатываемого запроса.
Метод и документированная запись. SoapServer::addSoapHeader(SoapHeader $header): void. Reflection PHP 8.5.11: SoapServer::addSoapHeader(SoapHeader $header): void. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
SoapHeader $header | Готовый SoapHeader для SOAP-ответа текущего запроса. |
Возврат и договор. Возвращаемого значения нет. Header сериализуется рядом с Body только в рамках активного handle().
Отказ. Метод разрешён только во время обработки активного SOAP request. Вызов до/после handle() даёт Error: «may be called only during SOAP request processing». Аргумент другого типа даёт TypeError; неверный namespace/data может дать несовместимый XML.
- Обработчик создаёт SoapHeader.
- addSoapHeader прикрепляет его к текущему response context.
- handle сериализует Header и Body.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
function ping(): string
{
$GLOBALS['manualServer']->addSoapHeader(new SoapHeader('urn:meta', 'RequestId', 'req-42'));
return 'pong';
}
$manualServer = new SoapServer(null, ['uri' => 'urn:manual']);
$manualServer->addFunction('ping');
$xml = manualHandle($manualServer, manualSoapRequest('ping', []));
echo manualXmlValue($xml, 'RequestId'), "\n";
echo manualXmlValue($xml), "\n";
Ожидаемый результат
req-42
pong
Header добавляется во время текущего handle. Он отделён от бизнес-return и подходит для correlation metadata. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
function checkLimit(): string
{
$GLOBALS['manualServer']->addSoapHeader(new SoapHeader('urn:meta', 'RateLimitRemaining', 9));
return 'accepted';
}
$manualServer = new SoapServer(null, ['uri' => 'urn:manual']);
$manualServer->addFunction('checkLimit');
$xml = manualHandle($manualServer, manualSoapRequest('checkLimit', []));
echo manualXmlValue($xml, 'RateLimitRemaining'), "\n";
echo manualXmlValue($xml), "\n";
Ожидаемый результат
9
accepted
Метаданные не приходится добавлять в каждую предметную response structure, если это согласовано SOAP-контрактом. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Это SOAP Header, не HTTP header(). Клиент получает его через outputHeaders __soapCall; namespace и mustUnderstand согласуют заранее.
Связанные операции: SoapHeader::__construct, SoapClient::__soapCall.
SoapServer::faultФормирует SOAP Fault и завершает нормальный ответ текущего запроса.
PHP 5+; $lang добавлен в PHP 8.5 · soap; XML/libxml; HTTP transport for real remote calls
SoapServer::fault( string $code, string $string, string $actor = "", mixed $details = null, string $name = "", string $lang = "" ): voidФормирует SOAP Fault и завершает нормальный ответ текущего запроса.
Метод и документированная запись. SoapServer::fault( string $code, string $string, string $actor = "", mixed $details = null, string $name = "", string $lang = "" ): void. Reflection PHP 8.5.11: SoapServer::fault(string $code, string $string, string $actor = "", mixed $details = null, string $name = "", string $lang = ""): void. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
string $code | SOAP fault code. Для SOAP 1.1 обычно Client/Server, для SOAP 1.2 — соответствующий QName/код договора. |
string $string | Безопасное клиентское описание ошибки без трассировки, SQL и секретов. |
string $actor = '' | URI участника/роли, который создал или должен обработать header/fault; null/пустая строка оставляют значение неуказанным. |
mixed $details = null | Структурированные дополнительные сведения Fault; не включайте внутренние секреты и stack trace. |
string $name = '' | Имя удалённой операции, cookie, fault binding или XML-узла — точный смысл задаёт текущий метод. |
string $lang = '' | Язык текста Fault для SOAP 1.2, например ru; параметр добавлен в PHP 8.5. |
Возврат и договор. Возвращаемого значения нет; метод отправляет fault code/string, actor, detail, optional WSDL fault name и с PHP 8.5 language.
Отказ. Метод формирует и выводит SOAP Fault, затем делает bailout: следующий PHP-код не выполняется. Вызывайте его на настроенном SoapServer — обычно из обработчика операции либо для отказа уровня endpoint. Секреты в detail/string уйдут клиенту.
- Обработчик обнаруживает предметный/технический отказ.
- Выбирает публичный code/message/detail.
- SoapServer сериализует Fault вместо успешного response.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
function reserve(string $sku): string
{
$GLOBALS['manualServer']->fault('Client', 'Нет остатка', 'urn:shop', ['sku' => $sku]);
return 'unreachable';
}
$manualServer = new SoapServer(null, ['uri' => 'urn:manual', 'encoding' => 'UTF-8']);
$manualServer->addFunction('reserve');
ob_start();
register_shutdown_function(static function (): void {
$xml = (string) ob_get_clean();
echo manualXmlValue($xml, 'faultcode'), "\n";
echo manualXmlValue($xml, 'faultstring'), "\n";
});
$manualServer->handle(manualSoapRequest('reserve', ['sku' => 'OUT']));
Ожидаемый результат
SOAP-ENV:Client
Нет остатка
Метод сразу формирует Fault текущего request; код после него не должен считаться продолжением успешной операции. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
function reject(): string
{
$GLOBALS['manualServer']->fault('Sender', 'Неверный заказ', '', null, '', 'ru');
return 'unreachable';
}
$manualServer = new SoapServer(null, ['uri' => 'urn:manual', 'soap_version' => SOAP_1_2, 'encoding' => 'UTF-8']);
$manualServer->addFunction('reject');
$request = str_replace(
'http://schemas.xmlsoap.org/soap/envelope/',
'http://www.w3.org/2003/05/soap-envelope',
manualSoapRequest('reject', []),
);
ob_start();
register_shutdown_function(static function (): void {
$xml = (string) ob_get_clean();
echo str_contains($xml, 'xml:lang="ru"') ? "lang=ru\n" : "lang missing\n";
echo manualXmlValue($xml, 'Text'), "\n";
});
$manualServer->handle($request);
Ожидаемый результат
lang=ru
Неверный заказ
Параметр lang добавлен в PHP 8.5 для соответствия SOAP 1.2. Код Fault для реального сервиса сверяют со спецификацией. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Client/Sender используют для проблем запроса, Server/Receiver — для неспособности обработать корректный запрос, но точные QName задаёт договор. Внутренний exception логируют отдельно.
Связанные операции: SoapFault::__construct, SoapServer::handle.
SoapServer::getFunctionsВозвращает список операций, зарегистрированных через addFunction, setClass или setObject.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapServer::getFunctions(): arrayВозвращает список операций, зарегистрированных через addFunction, setClass или setObject.
Метод и документированная запись. SoapServer::getFunctions(): array. Reflection PHP 8.5.11: SoapServer::getFunctions(): array. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
| Аргументов нет | Метод читает состояние клиента/сервера, созданное предыдущими вызовами. |
Возврат и договор. Возвращает array имён. Список отражает текущий server registry, а не полный WSDL contract/доступность зависимостей.
Отказ. Совпавшее имя ещё не доказывает совместимость параметров/return с WSDL.
- Код регистрирует обработчики.
- Метод читает registry.
- Тест сравнивает allowlist с ожидаемым API.
<?php
declare(strict_types=1);
function ping(): string { return 'pong'; }
function health(): string { return 'ok'; }
$server = new SoapServer(null, ['uri' => 'urn:manual']);
$server->addFunction(['ping', 'health']);
$names = $server->getFunctions();
sort($names);
echo implode(', ', $names), "\n";
Ожидаемый результат
health, ping
Такой smoke-check подтверждает allowlist до запуска HTTP endpoint. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
final class CatalogService
{
public function find(string $sku): string { return $sku; }
public function price(string $sku): int { return 100; }
private function secret(): string { return 'hidden'; }
}
$server = new SoapServer(null, ['uri' => 'urn:manual']);
$server->setObject(new CatalogService());
$names = $server->getFunctions();
sort($names);
echo implode(', ', $names), "\n";
Ожидаемый результат
find, price
getFunctions учитывает setObject так же, как setClass: внешними становятся публичные методы; private helper не экспортируется. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Используйте как smoke-check и источник диагностик, а contract tests строите на WSDL + sample requests/faults.
Связанные операции: SoapServer::addFunction, SoapServer::setClass, SoapServer::setObject.
SoapServer::__getLastResponseВозвращает последний XML, сформированный SoapServer, если включён <code>trace</code>.
PHP 8.4+ · soap; XML/libxml; HTTP transport for real remote calls
SoapServer::__getLastResponse(): ?stringВозвращает последний XML, сформированный SoapServer, если включён trace.
Метод и документированная запись. SoapServer::__getLastResponse(): ?string. Reflection PHP 8.5.11: SoapServer::__getLastResponse(): ?string. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
| Аргументов нет | Метод читает состояние клиента/сервера, созданное предыдущими вызовами. |
Возврат и договор. Возвращает string или null. Метод доступен с PHP 8.4.
Отказ. До handle или без trace возвращает null. XML способен содержать персональные/секретные данные.
- handle сериализует return/Fault.
- Trace сохраняет копию Envelope.
- Метод отдаёт её для теста/диагностики.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
function ping(): string { return 'pong'; }
$server = new SoapServer(null, ['uri' => 'urn:manual', 'trace' => true]);
$server->addFunction('ping');
$output = manualHandle($server, manualSoapRequest('ping', []));
$saved = $server->__getLastResponse();
echo is_string($saved) && $saved === $output ? "same response\n" : "different\n";
echo manualXmlValue($output), "\n";
Ожидаемый результат
same response
pong
PHP 8.4+ позволяет читать именно response текущего server object при trace=true. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
function ping(): string { return 'pong'; }
$server = new SoapServer(null, ['uri' => 'urn:manual', 'trace' => false]);
$server->addFunction('ping');
manualHandle($server, manualSoapRequest('ping', []));
echo $server->__getLastResponse() === null ? "trace is off\n" : "response retained\n";
Ожидаемый результат
trace is off
Отсутствие копии не означает, что ответ не сформирован: trace — отдельная диагностическая опция. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Используйте в contract tests и ограниченной диагностике. Не складывайте полный response каждого production-вызова без маскирования/retention policy.
Связанные операции: SoapServer::handle, SoapClient::__getLastResponse.
SoapServer::handleРазбирает SOAP request, вызывает зарегистрированный обработчик и выводит SOAP response.
PHP 5+; $request nullable с PHP 8.0 · soap; XML/libxml; HTTP transport for real remote calls
SoapServer::handle(?string $request = null): voidРазбирает SOAP request, вызывает зарегистрированный обработчик и выводит SOAP response.
Метод и документированная запись. SoapServer::handle(?string $request = null): void. Reflection PHP 8.5.11: SoapServer::handle(?string $request = null): void. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
?string $request = null | Полный XML SOAP Envelope. В handle(null) сервер читает raw POST body; в тесте строку можно передать явно. |
Возврат и договор. Возвращаемого значения нет: XML пишется в output. С явной строкой обрабатывает её; с null читает raw POST body.
Отказ. Невалидный XML/operation/handler error превращается в Fault либо PHP error согласно handler/send_errors. Любой лишний output до Envelope ломает ответ. С PHP 8.0 параметр request nullable: null читает raw POST body.
- Получает Envelope.
- Проверяет версию/body/operation и декодирует аргументы.
- Вызывает allowlisted handler.
- Сериализует return/header/fault в output.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
function multiply(int $a, int $b): int { return $a * $b; }
$server = new SoapServer(null, ['uri' => 'urn:manual']);
$server->addFunction('multiply');
$request = manualSoapRequest('multiply', ['a' => 6, 'b' => 7]);
$response = manualHandle($server, $request);
echo manualXmlValue($response), "\n";
Ожидаемый результат
42
Явная строка удобна в unit/contract test: видны входной Envelope, выбранный обработчик и точный результат. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
$url = getenv('SOAP_TEST_URL') ?: throw new RuntimeException('SOAP_TEST_URL missing');
$client = new SoapClient(null, ['location' => $url, 'uri' => 'urn:manual']);
echo $client->__soapCall('greet', [new SoapParam('Мир', 'name')]), "\n";
Ожидаемый результат
Здравствуйте, Мир
В server fixture вызывается handle() без аргумента: ext/soap читает реальный HTTP request body, отправленный SoapClient. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; HTTP endpoint — одноразовый loopback-сервер, без внешней сети.
Тонкости. Не echo/var_dump до/во время handle; журнал пишите в error log. HTTP route должен принимать нужный method/content type и иметь limits на body/time/concurrency.
Связанные операции: SoapServer::__construct, SoapServer::fault, use_soap_error_handler.
SoapServer::setClassЭкспортирует публичные методы класса и создаёт handler с переданными constructor args.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapServer::setClass(string $class, mixed ...$args): voidЭкспортирует публичные методы класса и создаёт handler с переданными constructor args.
Метод и документированная запись. SoapServer::setClass(string $class, mixed ...$args): void. Reflection PHP 8.5.11: SoapServer::setClass(string $class, mixed ...$args /* optional; Reflection default unavailable */): void. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
string $class | Имя класса обработчика. Публичные методы становятся операциями сервера. |
mixed ...$args | Аргументы операции. Для SOAP-вызова это упорядоченный/именованный массив; для setClass — variadic аргументы конструктора обработчика. |
Возврат и договор. Возвращаемого значения нет. Вызов меняет модель обработчиков сервера; persistence относится именно к объекту этого класса.
Отказ. Ошибка конструктора/метода превращается по server error policy. Публичный служебный метод может случайно стать доступной операцией.
- Регистрируется имя класса и constructor args.
- На request SoapServer создаёт/восстанавливает объект.
- Operation вызывает соответствующий публичный метод.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
final class DeliveryService
{
public function estimate(string $city): string { return $city . ': 2 дня'; }
}
$server = new SoapServer(null, ['uri' => 'urn:manual']);
$server->setClass(DeliveryService::class);
$response = manualHandle($server, manualSoapRequest('estimate', ['city' => 'Тула']));
echo manualXmlValue($response), "\n";
Ожидаемый результат
Тула: 2 дня
Методы одного предметного сервиса и его зависимости собраны в объекте, а не разбросаны по глобальным функциям. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
final class PriceService
{
public function __construct(private string $currency, private int $rate) {}
public function quote(int $units): string { return ($units * $this->rate) . ' ' . $this->currency; }
}
$server = new SoapServer(null, ['uri' => 'urn:manual']);
$server->setClass(PriceService::class, 'RUB', 125);
$response = manualHandle($server, manualSoapRequest('quote', ['units' => 3]));
echo manualXmlValue($response), "\n";
Ожидаемый результат
375 RUB
Variadic args идут в конструктор при создании handler object. Секреты лучше передавать через настроенный dependency container, а не hardcode. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. Делайте SOAP-facing class узким фасадом; валидация и domain service остаются отдельными зависимостями. Сверяйте public methods с WSDL allowlist.
Связанные операции: SoapServer::setObject, SoapServer::setPersistence, SoapServer::getFunctions.
SoapServer::setObjectНазначает конкретный уже созданный объект обработчиком SOAP-операций.
PHP 5+; актуальные изменения отмечены · soap; XML/libxml; HTTP transport for real remote calls
SoapServer::setObject(object $object): voidНазначает конкретный уже созданный объект обработчиком SOAP-операций.
Метод и документированная запись. SoapServer::setObject(object $object): void. Reflection PHP 8.5.11: SoapServer::setObject(object $object): void. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
object $object | Проверяемое значение либо конкретный объект-обработчик — смысл зависит от операции; тип указан в сигнатуре. |
Возврат и договор. Возвращаемого значения нет. Публичные методы объекта становятся registry сервера; объект используется в текущем request/process.
Отказ. Несовместимый public method/исключение объекта даст Fault. Объект с request-specific данными нельзя безопасно делить между чужими запросами.
- Приложение собирает object с зависимостями.
- setObject передаёт его SoapServer.
- handle вызывает метод на том же экземпляре.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
final class WarehouseService
{
public function __construct(private string $warehouse) {}
public function locate(string $sku): string { return $sku . '@' . $this->warehouse; }
}
$handler = new WarehouseService('MSK-1');
$server = new SoapServer(null, ['uri' => 'urn:manual']);
$server->setObject($handler);
$response = manualHandle($server, manualSoapRequest('locate', ['sku' => 'A-17']));
echo manualXmlValue($response), "\n";
Ожидаемый результат
A-17@MSK-1
Объект можно заранее собрать с проверенной конфигурацией и зависимостями. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
<?php
declare(strict_types=1);
require __DIR__ . '/soap-server-helper.php';
final class StatusStub
{
public function __construct(private string $status) {}
public function orderStatus(int $id): string { return $id . ':' . $this->status; }
}
$server = new SoapServer(null, ['uri' => 'urn:manual']);
$server->setObject(new StatusStub('ready'));
$response = manualHandle($server, manualSoapRequest('orderStatus', ['id' => 731]));
echo manualXmlValue($response), "\n";
Ожидаемый результат
731:ready
Contract test управляет состоянием handler object без БД/банка, а сериализацию оставляет настоящему SoapServer. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; внешняя сеть и рабочие сервисы не используются.
Тонкости. setObject и setClass — альтернативные модели. Для session persistence официальный механизм относится к setClass; long-running worker требует явного сброса mutable state.
Связанные операции: SoapServer::setClass, SoapServer::getFunctions.
SoapServer::setPersistenceВыбирает новый handler object на request или сохранение объекта setClass в PHP session.
PHP 5+; session-extension failure исправлен/явно сигнализируется с PHP 8.4 · soap; XML/libxml; HTTP transport for real remote calls
SoapServer::setPersistence(int $mode): voidВыбирает новый handler object на request или сохранение объекта setClass в PHP session.
Метод и документированная запись. SoapServer::setPersistence(int $mode): void. Reflection PHP 8.5.11: SoapServer::setPersistence(int $mode): void. Круглые скобки запускают операцию, аргументы передают входные данные, а возвращаемое значение можно сохранить справа от =. Для SOAP важно разделять PHP-значение, XML Envelope, HTTP transport и удалённый обработчик: ошибка на каждом слое выглядит по-разному. Как устроен вызов функции.
| Параметр | Что передать и зачем |
|---|---|
int $mode | SOAP_PERSISTENCE_REQUEST либо SOAP_PERSISTENCE_SESSION; session mode требует session_start() до установки. |
Возврат и договор. Возвращаемого значения нет. Допустимы SOAP_PERSISTENCE_REQUEST и SOAP_PERSISTENCE_SESSION. Session mode требует session_start() до вызова.
Отказ. В function mode метод всегда даёт Error. После setClass неизвестный mode даёт ValueError; разрешены только REQUEST/SESSION. Для SESSION документация требует session_start() до setPersistence; с PHP 8.4 отсутствие session extension даёт Error вместо прежнего тихого отказа. Resources/DB connections не сериализуются нормально.
- setClass задаёт handler class.
- Request mode создаёт объект заново.
- Session mode восстанавливает/сохраняет object state по session cookie.
<?php
declare(strict_types=1);
$base = getenv('SOAP_TEST_URL') ?: throw new RuntimeException('SOAP_TEST_URL missing');
$client = new SoapClient(null, ['location' => $base . '?persistence=request', 'uri' => 'urn:manual']);
echo $client->__soapCall('increment', []), "\n";
echo $client->__soapCall('increment', []), "\n";
Ожидаемый результат
1
1
SOAP_PERSISTENCE_REQUEST — значение по умолчанию: каждый HTTP request получает новый CounterService. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; HTTP endpoint — одноразовый loopback-сервер, без внешней сети.
<?php
declare(strict_types=1);
$base = getenv('SOAP_TEST_URL') ?: throw new RuntimeException('SOAP_TEST_URL missing');
$client = new SoapClient(null, ['location' => $base . '?persistence=session', 'uri' => 'urn:manual']);
echo $client->__soapCall('increment', []), "\n";
echo $client->__soapCall('increment', []), "\n";
final class PersistenceProbe {}
$classServer = new SoapServer(null, ['uri' => 'urn:manual']);
$classServer->setClass(PersistenceProbe::class);
try {
$classServer->setPersistence(999);
} catch (ValueError $error) {
echo "invalid mode: ValueError\n";
}
$functionServer = new SoapServer(null, ['uri' => 'urn:manual']);
try {
$functionServer->setPersistence(SOAP_PERSISTENCE_REQUEST);
} catch (Error $error) {
echo "function mode: Error\n";
}
Ожидаемый результат
1
2
invalid mode: ValueError
function mode: Error
SOAP_PERSISTENCE_SESSION сериализует handler object в PHP session; затем пример фиксирует ValueError неверного mode в class mode и Error попытки persistence в function mode. Пример выполнен на локальном PHP 8.5.11 с process-only ext/soap; HTTP endpoint — одноразовый loopback-сервер, без внешней сети.
Тонкости. Stateful SOAP усложняет масштабирование, блокировки сессий и повтор запросов. Предпочитайте явный state в БД/cache; при необходимости реализуйте __sleep/__wakeup для resources и защищайте session cookie.
Связанные операции: SoapServer::setClass, SoapClient::__getCookies.
Источники и обсуждения
- PHP Manual: SOAP
- PHP Manual: Installing/Configuring
- PHP Manual: Requirements
- PHP Manual: Installation
- PHP Manual: Runtime Configuration
- PHP Manual: Predefined Constants
- PHP Manual: SOAP Functions
- PHP Manual: is_soap_fault
- PHP Manual: use_soap_error_handler
- PHP Manual: The SoapClient class
- PHP Manual: SoapClient::__call
- PHP Manual: SoapClient::__construct
- PHP Manual: SoapClient::__doRequest
- PHP Manual: SoapClient::__getCookies
- PHP Manual: SoapClient::__getFunctions
- PHP Manual: SoapClient::__getLastRequest
- PHP Manual: SoapClient::__getLastRequestHeaders
- PHP Manual: SoapClient::__getLastResponse
- PHP Manual: SoapClient::__getLastResponseHeaders
- PHP Manual: SoapClient::__getTypes
- PHP Manual: SoapClient::__setCookie
- PHP Manual: SoapClient::__setLocation
- PHP Manual: SoapClient::__setSoapHeaders
- PHP Manual: SoapClient::__soapCall
- PHP Manual: The SoapServer class
- PHP Manual: SoapServer::addFunction
- PHP Manual: SoapServer::addSoapHeader
- PHP Manual: SoapServer::__construct
- PHP Manual: SoapServer::fault
- PHP Manual: SoapServer::getFunctions
- PHP Manual: SoapServer::__getLastResponse
- PHP Manual: SoapServer::handle
- PHP Manual: SoapServer::setClass
- PHP Manual: SoapServer::setObject
- PHP Manual: SoapServer::setPersistence
- PHP Manual: The SoapFault class
- PHP Manual: SoapFault::__construct
- PHP Manual: SoapFault::__toString
- PHP Manual: The SoapHeader class
- PHP Manual: SoapHeader::__construct
- PHP Manual: The SoapParam class
- PHP Manual: SoapParam::__construct
- PHP Manual: The SoapVar class
- PHP Manual: SoapVar::__construct
- PHP Manual: The Soap\Sdl class
- PHP Manual: The Soap\Url class
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


