我如何使用从使用 php 和 Soap 的抽象复杂类型派生的复杂类型
How do i use a complex type derived from an abstract complex type using php and Soap
我最近开始使用 SOAP,但发现很难理解抽象复杂类型的使用。
我正在尝试向 wsdl 发出请求,但我一直收到错误消息。 '指定的类型是抽象的:name="HomeAffairsIDVRequestedBase".
我的php如下:
$result = $this->soap->__soapCall('PlaceRequest',array('PlaceRequest'=>
array('request' =>
array(
'type'=> 'tns:HomeAffairsIDVStandardRequest',
"IsBatchSearch"=>false,
"ParentRequestId"=>0,
"Reference"=>'test',
"Requester"=>'axxess',
"SessionId"=>'true',
"IdNumber"=>$this->idNumber
))));
目标wsdl部分如下
<s:element name="PlaceRequest">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="request" type="tns:HomeAffairsIDVRequestBase"/>
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="HomeAffairsIDVRequestBase" abstract="true">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="IsBatchSearch" type="s:boolean"/>
<s:element minOccurs="1" maxOccurs="1" name="ParentRequestId" nillable="true" type="s:int"/>
<s:element minOccurs="0" maxOccurs="1" name="Reference" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="Requester" type="s:string"/>
<s:element minOccurs="1" maxOccurs="1" name="SessionId" nillable="true" type="s1:guid"/>
</s:sequence>
</s:complexType>
<s:complexType name="HomeAffairsIDVRequest" abstract="true">
<s:complexContent mixed="false">
<s:extension base="tns:HomeAffairsIDVRequestBase">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="IdNumber" type="s:string"/>
</s:sequence>
</s:extension>
</s:complexContent>
</s:complexType>
<s:complexType name="HomeAffairsIDVStandardRequest">
<s:complexContent mixed="false">
<s:extension base="tns:HomeAffairsIDVRequest"/>
</s:complexContent>
</s:complexType>
<s:complexType name="HomeAffairsIDVAdvancedRequest">
<s:complexContent mixed="false">
<s:extension base="tns:HomeAffairsIDVRequest"/>
</s:complexContent>
</s:complexType>
注意:我无法编辑 wsdl。
您可以从 wsdl 读取复杂类型定义作为 php class 定义。每个复杂类型都是一个 php 值对象。抽象复杂类型是抽象的值对象,可以继承。
因为我们已经定义了复杂类型,所以我们可以构建我们的 php classes.
abstract class HomeAffairsIDVRequestBase
{
protected bool $IsBatchSearch;
protected int $ParentRequestId;
protected ?string $Reference;
protected ?string $Requester;
protected string $SessionId;
public function getIsBatchSearch(): bool
{
return $this->IsBatchSearch;
}
public function setIsBatchSearch(bool $isBatchSearch): self
{
$this->isBatchSearch = $isBatchSearch;
return $this;
}
public function getParentRequestId(): int
{
return $this->ParentRequestId;
}
public function setParentRequestId(int $parentRequestId): self
{
$this->ParentRequestId = $parentRequestId;
return $this;
}
public function getReference(): ?string
{
return $this->Reference;
}
public function setReference(string $reference): self
{
$this->Reference = $reference;
return $this;
}
public function getRequester(): ?string
{
return $this->Requester;
}
public function setRequester(string $requester): self
{
$this->Requester = $requester;
return $this;
}
public function getSessionId(): string
{
return $this->SessionId;
}
public function setSessionId(string $sessionId): self
{
$this->SessionId = $sessionId;
return $this;
}
}
这是我们的第一个抽象复杂类型定义 HomeAffairsIDVRequestBase
作为抽象 php class。如您所见,抽象 class 具有所有属性,这些属性在 wsdl 文件中为此复杂类型定义。除此之外,我们还有 getter 和 setter 方法来更好地处理 class 属性。
当我们查看 HomeAffairsIDVStandardRequest
的定义时,我们可以看到它继承自 HomeAffairsIDVRequest
。考虑到这一点,我们必须写更多 php classes。
abstract class HomeAffairsIDVRequest extends HomeAffairsIDVRequestBase
{
protected ?string $IdNumber;
public function getIdNumber(): ?string
{
return $this->IdNumber;
}
public function setIdNumber(?string $idNumber): self
{
$this->IdNumber = $idNumber;
return $this;
}
}
class HomeAffairsIDVStandardRequest extends HomeAffairsIDVRequest
{
}
由于复杂类型 HomeAffairsIDVStandardRequest
和 HomeAffairsIDVAdvancedRequest
之一不是抽象的,因此可以使用此 classes 作为请求。请记住,abstract php classes 不能直接初始化。 wsdl 中的抽象复杂类型也是如此。
现在我们需要请求元素作为 class。这是我们 soap 请求中的父元素。 PlaceRequest
元素只有一个 属性 称为 request
。由于此元素是 HomeAffairsIDVRequestBase
的继承且此定义是抽象的,因此我们必须稍后在请求中使用类型属性。
class PlaceRequest
{
protected HomeAffairsIDVRequestBase $request;
public function getRequest(): HomeAffairsIDVRequestBase
{
return $this->request;
}
public function setRequest(HomeAffairsIDVRequestBase $request): self
{
$this->request = $request;
return $this;
}
}
到目前为止,我们的数据结构是 PHP 值对象。到目前为止,这就是我们所需要的。现在让我们看看一个可能的请求。
try {
$wsdl = 'https://path.to.your.wsdl.file.com?wsdl';
$client = new SoapClient($wsdl, [
'exceptions' => true,
'trace' => true,
]);
// initialize our value object
$standard = (new HomeAffairsIDVStandardRequest())
->setIsBatchSearch(false)
->setParentRequestId(0)
->setReference('test')
->setRequester('requester')
->setSessionId('true')
->setIdNumber($idNumber);
// initialize our request element
$request = (new PlaceRequest())
->setRequest($standard);
$response = $client->placeRequest($request);
} catch (SoapFault $fault) {
// error handling like var_dump($fault)
}
因为我没有看到完整的 wsdl 内容,所以我不能说请求 XML 应该是什么样子。上面显示的结果可能会导致 soap 故障。在这种情况下,请尝试以下示例。
更改 PlaceRequest
class 中的类型提示。
class PlaceRequest
{
protected SoapVar $request;
public function getRequest(): SoapVar
{
return $this->request;
}
public function setRequest(SoapVar $request): self
{
$this->request = $request;
return $this;
}
}
之后使用 $standard
实例创建一个新的 SoapVar 实例。
// we 've already defined the $standard object above (sets an type attribute for the request node)
$standard = new SoapVar($standard, SOAP_ENC_OBJECT, 'HomeAffairsIDVStandardRequest', 'http://your.namespace.tld/namespace', 'request', 'http://your.namespace.tld/namespace');
// initialise the request element and set the soap var parameter
$request = (new PlaceRequest())
->setRequest($standard);
// send it via soap client
$client->PlaceRequest($request);
作为附加信息,您应该始终查看发送 xml 和接收 xml 以更好地了解错误处理。我们在初始化 soap 客户端时设置了 trace
选项。这使我们能够看到最后一个请求和最后一个响应是什么。
...
} catch (SoapFault $fault) {
if ($client) {
// get last request
var_dump($client->__getLastRequest());
// get last response
var_dump($client->__getLastResponse());
}
}
我最近开始使用 SOAP,但发现很难理解抽象复杂类型的使用。
我正在尝试向 wsdl 发出请求,但我一直收到错误消息。 '指定的类型是抽象的:name="HomeAffairsIDVRequestedBase".
我的php如下:
$result = $this->soap->__soapCall('PlaceRequest',array('PlaceRequest'=>
array('request' =>
array(
'type'=> 'tns:HomeAffairsIDVStandardRequest',
"IsBatchSearch"=>false,
"ParentRequestId"=>0,
"Reference"=>'test',
"Requester"=>'axxess',
"SessionId"=>'true',
"IdNumber"=>$this->idNumber
))));
目标wsdl部分如下
<s:element name="PlaceRequest">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="request" type="tns:HomeAffairsIDVRequestBase"/>
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="HomeAffairsIDVRequestBase" abstract="true">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="IsBatchSearch" type="s:boolean"/>
<s:element minOccurs="1" maxOccurs="1" name="ParentRequestId" nillable="true" type="s:int"/>
<s:element minOccurs="0" maxOccurs="1" name="Reference" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="Requester" type="s:string"/>
<s:element minOccurs="1" maxOccurs="1" name="SessionId" nillable="true" type="s1:guid"/>
</s:sequence>
</s:complexType>
<s:complexType name="HomeAffairsIDVRequest" abstract="true">
<s:complexContent mixed="false">
<s:extension base="tns:HomeAffairsIDVRequestBase">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="IdNumber" type="s:string"/>
</s:sequence>
</s:extension>
</s:complexContent>
</s:complexType>
<s:complexType name="HomeAffairsIDVStandardRequest">
<s:complexContent mixed="false">
<s:extension base="tns:HomeAffairsIDVRequest"/>
</s:complexContent>
</s:complexType>
<s:complexType name="HomeAffairsIDVAdvancedRequest">
<s:complexContent mixed="false">
<s:extension base="tns:HomeAffairsIDVRequest"/>
</s:complexContent>
</s:complexType>
注意:我无法编辑 wsdl。
您可以从 wsdl 读取复杂类型定义作为 php class 定义。每个复杂类型都是一个 php 值对象。抽象复杂类型是抽象的值对象,可以继承。
因为我们已经定义了复杂类型,所以我们可以构建我们的 php classes.
abstract class HomeAffairsIDVRequestBase
{
protected bool $IsBatchSearch;
protected int $ParentRequestId;
protected ?string $Reference;
protected ?string $Requester;
protected string $SessionId;
public function getIsBatchSearch(): bool
{
return $this->IsBatchSearch;
}
public function setIsBatchSearch(bool $isBatchSearch): self
{
$this->isBatchSearch = $isBatchSearch;
return $this;
}
public function getParentRequestId(): int
{
return $this->ParentRequestId;
}
public function setParentRequestId(int $parentRequestId): self
{
$this->ParentRequestId = $parentRequestId;
return $this;
}
public function getReference(): ?string
{
return $this->Reference;
}
public function setReference(string $reference): self
{
$this->Reference = $reference;
return $this;
}
public function getRequester(): ?string
{
return $this->Requester;
}
public function setRequester(string $requester): self
{
$this->Requester = $requester;
return $this;
}
public function getSessionId(): string
{
return $this->SessionId;
}
public function setSessionId(string $sessionId): self
{
$this->SessionId = $sessionId;
return $this;
}
}
这是我们的第一个抽象复杂类型定义 HomeAffairsIDVRequestBase
作为抽象 php class。如您所见,抽象 class 具有所有属性,这些属性在 wsdl 文件中为此复杂类型定义。除此之外,我们还有 getter 和 setter 方法来更好地处理 class 属性。
当我们查看 HomeAffairsIDVStandardRequest
的定义时,我们可以看到它继承自 HomeAffairsIDVRequest
。考虑到这一点,我们必须写更多 php classes。
abstract class HomeAffairsIDVRequest extends HomeAffairsIDVRequestBase
{
protected ?string $IdNumber;
public function getIdNumber(): ?string
{
return $this->IdNumber;
}
public function setIdNumber(?string $idNumber): self
{
$this->IdNumber = $idNumber;
return $this;
}
}
class HomeAffairsIDVStandardRequest extends HomeAffairsIDVRequest
{
}
由于复杂类型 HomeAffairsIDVStandardRequest
和 HomeAffairsIDVAdvancedRequest
之一不是抽象的,因此可以使用此 classes 作为请求。请记住,abstract php classes 不能直接初始化。 wsdl 中的抽象复杂类型也是如此。
现在我们需要请求元素作为 class。这是我们 soap 请求中的父元素。 PlaceRequest
元素只有一个 属性 称为 request
。由于此元素是 HomeAffairsIDVRequestBase
的继承且此定义是抽象的,因此我们必须稍后在请求中使用类型属性。
class PlaceRequest
{
protected HomeAffairsIDVRequestBase $request;
public function getRequest(): HomeAffairsIDVRequestBase
{
return $this->request;
}
public function setRequest(HomeAffairsIDVRequestBase $request): self
{
$this->request = $request;
return $this;
}
}
到目前为止,我们的数据结构是 PHP 值对象。到目前为止,这就是我们所需要的。现在让我们看看一个可能的请求。
try {
$wsdl = 'https://path.to.your.wsdl.file.com?wsdl';
$client = new SoapClient($wsdl, [
'exceptions' => true,
'trace' => true,
]);
// initialize our value object
$standard = (new HomeAffairsIDVStandardRequest())
->setIsBatchSearch(false)
->setParentRequestId(0)
->setReference('test')
->setRequester('requester')
->setSessionId('true')
->setIdNumber($idNumber);
// initialize our request element
$request = (new PlaceRequest())
->setRequest($standard);
$response = $client->placeRequest($request);
} catch (SoapFault $fault) {
// error handling like var_dump($fault)
}
因为我没有看到完整的 wsdl 内容,所以我不能说请求 XML 应该是什么样子。上面显示的结果可能会导致 soap 故障。在这种情况下,请尝试以下示例。
更改 PlaceRequest
class 中的类型提示。
class PlaceRequest
{
protected SoapVar $request;
public function getRequest(): SoapVar
{
return $this->request;
}
public function setRequest(SoapVar $request): self
{
$this->request = $request;
return $this;
}
}
之后使用 $standard
实例创建一个新的 SoapVar 实例。
// we 've already defined the $standard object above (sets an type attribute for the request node)
$standard = new SoapVar($standard, SOAP_ENC_OBJECT, 'HomeAffairsIDVStandardRequest', 'http://your.namespace.tld/namespace', 'request', 'http://your.namespace.tld/namespace');
// initialise the request element and set the soap var parameter
$request = (new PlaceRequest())
->setRequest($standard);
// send it via soap client
$client->PlaceRequest($request);
作为附加信息,您应该始终查看发送 xml 和接收 xml 以更好地了解错误处理。我们在初始化 soap 客户端时设置了 trace
选项。这使我们能够看到最后一个请求和最后一个响应是什么。
...
} catch (SoapFault $fault) {
if ($client) {
// get last request
var_dump($client->__getLastRequest());
// get last response
var_dump($client->__getLastResponse());
}
}