SoapServer 类

(PHP 5, PHP 7, PHP 8)

简介

SoapServer 类为 » SOAP 1.1» SOAP 1.2 协议提供服务器。它可以与 WSDL 服务描述一起使用或不使用。

类概要

class SoapServer {
/* 属性 */
private ?SoapFault $__soap_fault = null;
/* 方法 */
public __construct(?string $wsdl, array $options = [])
public addFunction(array|string|int $functions): void
public addSoapHeader(SoapHeader $header): void
public fault(
    string $code,
    string $string,
    string $actor = "",
    mixed $details = null,
    string $name = ""
): void
public handle(?string $request = null): void
public setClass(string $class, mixed ...$args): void
public setObject(object $object): void
public setPersistence(int $mode): void
}

属性

service

__soap_fault

目录

添加注释

用户贡献的注释 10 个注释

php1221 at klox dot net
12 年前
虽然网上有很多提到 SoapServer 不支持 SOAP 标头,但事实并非如此。

在您的类中,如果您声明一个函数,其名称与标头相同,则在收到该标头时将调用该函数。

<?php
class MySoapService {
private
$user_is_valid;

function
MyHeader($header) {
if ((isset(
$header->Username)) && (isset($header->Password))) {
if (
ValidateUser($header->Username, $header->Password)) {
$user_is_valid = true;
}
}
}

function
MySoapRequest($request) {
if (
$user_is_valid) {
// 处理请求
}
else {
throw new
MyFault("MySoapRequest", "用户无效.");
}
}
}
?>
mail at borisd dot ru
5 年前
如果您想在 linux 上运行一个虚拟的 SoapServer 作为测试的守护进程,您需要

1. 在您的 wsdl 中设置位置 "localhost:12312/soapServer.php",例如

<wsdl:service name="ServiceName">
<wsdl:port name="ServiceNamePort" binding="tns:ServiceNameBinding">
<soap:address location="http://localhost:12312/soapServer.php" />
</wsdl:port>
</wsdl:service>

2. 编写您的测试服务器,例如

<?php
/*
* 服务器
*/
class TestSoapServer
{
public function
getMessage()
{
return
'Hello, World!';
}
}
$options = ['uri' => 'http://localhost:12312/'];
$server = new SoapServer(null, $options);
$server->setClass('TestSoapServer');
$server->handle();

?>

3. 使用 `php -S localhost:12312` 运行它(在同一文件夹中)

只要您根据您的 wsdl 发出请求,它最终都会到达您的 "服务器"。
carlos dot vini at gmail dot com
14 年前
SoapServer 不支持带有 literal/document 的 WSDL。我有一个类

<?php
class My_Soap {
/**
* 返回 Hello World。
*
* @param string $world
* @return string
*/
public function getInterAdmins($world) {
return
'hello' . $world;
}
}
?>

为了解决这个问题,我必须创建一个代理类。
<?php
class My_Soap_LiteralDocumentProxy {
public function
__call($methodName, $args) {
$soapClass = new My_Soap();
$result = call_user_func_array(array($soapClass, $methodName), $args[0]);
return array(
$methodName . 'Result' => $result);
}
}
?>

现在,确保使用 My_Soap 创建 WSDL,并使用 My_Soap_LiteralDocumentProxy 创建服务器。

<?php

if (isset($_GET['wsdl'])) {
$wsdl = new Zend_Soap_AutoDiscover(); // 它生成 WSDL
$wsdl->setOperationBodyStyle(array(
'use' => 'literal'
));
$wsdl->setBindingStyle(array(
'style' => 'document'
));
$wsdl->setClass('My_Soap');
$wsdl->handle();
} else {
$server = new Zend_Soap_Server('http://localhost/something/webservice.php?wsdl');
$server->setClass('My_Soap_LiteralDocumentProxy');
$server->handle();
}

?>
softontherocks at gmail dot com
9 年前
我在这个 URL http://softontherocks.blogspot.com/2014/02/web-service-soap-con-php.html 发布了一个完整的 nusoap web 服务示例。

其中定义了服务器和调用 web 服务的客户端。

希望对您有所帮助。
dsubar at interna dot com
14 年前
不要将 SoapServer 和 SoapClient 放在同一个 PHP 文件中。这样做会导致不可预知的行为。在 Eclipse 中的 PHP 解释器中,一切都运行良好。在 MAMP 下,我遇到了一个未记录的错误。将客户端从与服务器相同的文件中移开后,一切正常。
s at dumdeedum dot com
10 年前
我当时运行的是 PHP 5.3.2,无论我多么小心地构建我的类/wsdl/客户端,都无法让 SOAP 标头正常工作。最终解决问题的方法是更新到最新的 PHP。不知道是哪里出了问题,还是什么原因,但保持更新永远不会错,它可以节省你数周的沮丧时间!
hawky83 at googlemail dot com
13 年前
另一个简单的 SOAP_SERVER 示例,包含错误处理、参数和 wsdl

服务器 (soap_all_srv.php)

<?php
// PEAR::SOAP einbinden
require_once "SOAP/Server.php";
$skiptrace =& PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
$skiptrace = true;

// Service-Class
class mytimeserv {

// __dispatch_map
public $__dispatch_map = array ();

// In/Out param -> __dispatch_map
public function __construct() {
$this->__dispatch_map["now"] =
array (
"in" => array("format" => "string"),
"out" => array("time" => "string"));
}

// get back __dispatch_map in __dispatch
public function __dispatch($methodname) {

if (isset(
$this->__dispatch_map[$methodname])) {
return
$this->__dispatch_map[$methodname];
}

return
NULL;
}

// servicemthod with parameters
function now ($format) {

// formaterror?
if (($format == null) || (trim($format) == "")) {

// send errormessage
return new SOAP_Fault("Kein Parameter angegeben","0815", "Client");
}

date_default_timezone_set('Europe/Berlin');

$time = date ($format);

// return SOAP-Obj.
return (new SOAP_Value('time','string', $time));
}
}

// service-class
$service = new mytimeserv();

// server
$ss = new SOAP_Server();

// add service with name
$ss->addObjectMap (&$service,"urn:mytimeserv");

// service or wsdl
if (isset($_SERVER["REQUEST_METHOD"])&& $_SERVER["REQUEST_METHOD"] == "POST") {

// postdata -> service
$ss->service ($HTTP_RAW_POST_DATA);

} else {

// wsdl-param in url
if (isset($_SERVER['QUERY_STRING']) && strcasecmp($_SERVER['QUERY_STRING'],'wsdl') == 0) {

// DISCO_Server for WSDL
require_once "SOAP/Disco.php";
$disco = new SOAP_DISCO_Server ($ss,"mytimeserv","My Time Service");

// set HTML-Header
header("Content-type: text/xml");

// return wsdl
print $disco->getWSDL ();
}
}

?>

客户端 (soap_all_client.php) (适用于 wsdl: http://example.com/soap_all_srv.php?wsdl)
<?php

require_once "SOAP/Client.php";

// SOAP/WSDL
$sw = new SOAP_WSDL ("http://example.com/soap_all_srv.php?wsdl");

// Proxy-Obj.
$proxy = $sw->getProxy ();

// servicemthod
$erg = $proxy->now ("H:i:s");

// return
print $erg."\n";

?>
junk2cm at gmx dot de
14 年前
由于 SoapServer 类缺乏处理 SOAP 标头的能力,因此以下解决方法适合我的需求,因为我必须通过 SOAP 标头进行身份验证。
1. 使用一个处理 SOAP 请求的类,并让该类的构造函数接收发送的标头。
2. 在调用 SoapServer 之前,从传入的原始数据中提取 SOAP 标头。
3. 使用 setClass 时,将提取的标头传递给处理类。

在您的服务器脚本中执行以下操作:
<?php
$hdr
= file_get_contents("php://input");
if (
strpos($hdr,'<s:Header>')===false) {
$hdr = null;
} else {
$hdr = explode('<s:Header>',$hdr);
$hdr = explode('</s:Header>',$hdr[1]);
$hdr = $hdr[0];
}
$srv = new SoapServer('Your_wsdl');
$srv->setClass("ServiceClass",$hdr);
$srv->handle();
?>

服务类如下所示
<?php
class ServiceClass {
var
$IsAuthenticated;

function
__construct($hdr) {
$this->IsAuthenticated = false;
if (
$hdr!=null) {
$this->header = simplexml_load_string($hdr);
// 您的身份验证代码在这里...
}
}

function
SomeFunctionOfTheService($a) {
if (
$this->IsAuthenticated) {
// 您的函数代码在这里...
}
}

}
?>
mikkel at nsales dot dk
14 年前
如果您想从 nusoap web 服务返回自定义对象数组,您需要像这样将对象转换为数组

<?php
$users
= array();
while(
$res = $db_obj->fetch_row())
{
$user = new user();
$user->Id = $res['id'];
$user->Username = $res['username'];
$user->Email = $res['email'];

$users[] = (array) $user;
}

return (
$users);
?>
phpman dot fulter47 at recursor dot net
12 年前
对于那些(像我一样)来自其他 SOAP 框架并感到困惑的人

- 使用 SoapServer 类创建的 PHP SOAP 服务器应用程序不能用作独立的 SOAP 服务器。
- 它需要一个 HTTP 服务器来接收 SOAP 请求,该服务器必须运行 PHP 引擎来执行 PHP SOAP 服务器脚本作为 CGI。

- 因此,PHP 中没有设置来控制 SOAP 服务器将监听请求的接口/端口 - 这是 HTTP 服务器的责任。

- "uri" 参数是一个 "id 值",用作 SOAP 响应的命名空间。它仅在没有使用 WSDL 文件(包含此设置)的情况下需要,即 "wsdl" 设置为 NULL。它 _不_ 控制 HTTP 服务器将在其上可达以进行请求的主机名/端口。
To Top