简体   繁体   English

如何使用从使用 php 和 Soap 的抽象复杂类型派生的复杂类型

[英]How do i use a complex type derived from an abstract complex type using php and Soap

I recently started working with SOAP but and finding it hard to understand the use of abstract complex types.我最近开始使用 SOAP 但发现很难理解抽象复杂类型的使用。

I am trying to place a request to a wsdl yet I keep getting the error.我正在尝试向 wsdl 发出请求,但我不断收到错误消息。 'The specified type is abstract: name="HomeAffairsIDVRequestedBase". '指定的类型是抽象的:name="HomeAffairsIDVRequestedBase"。

My php is as follows:我的 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
                                                            ))));

and the targeted wsdl section is as follows目标 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>

Note: I can not edit the wsdl.注意:我无法编辑 wsdl。

You can read complex type definitions from the wsdl as php class definitions.您可以从 wsdl 中读取复杂类型定义作为 php class 定义。 Each complex type is a php value object.每个复杂类型是一个 php 值 object。 Abstract complex types are abstract value object, which can be inherited from.抽象复杂类型是抽象值object,可以继承自。

As we have the complex types defined, we can build our php classes.由于我们定义了复杂类型,我们可以构建我们的 php 类。

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;
    }
}

This is our first abstract complex type definition HomeAffairsIDVRequestBase as an abstract php class.这是我们的第一个抽象复杂类型定义HomeAffairsIDVRequestBase作为抽象 php class。 As you can see the abstract class has all the properties, which are defined in the wsdl file for this complex type.如您所见,抽象 class 具有所有属性,这些属性在 wsdl 文件中为这种复杂类型定义。 Beside that we have getter and setter methods for a better handling of the class properties.除此之外,我们还有 getter 和 setter 方法可以更好地处理 class 属性。

When we look at the definition for HomeAffairsIDVStandardRequest we can see, that it inherits from HomeAffairsIDVRequest .当我们查看HomeAffairsIDVStandardRequest的定义时,我们可以看到,它继承自HomeAffairsIDVRequest This in mind we have to write to more php classes.记住这一点,我们必须写更多的 php 类。

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
{

}

Since one of the complex types HomeAffairsIDVStandardRequest and HomeAffairsIDVAdvancedRequest is not abstract, wie can use this classes for the request.由于复杂类型HomeAffairsIDVStandardRequestHomeAffairsIDVAdvancedRequest不是抽象的,因此可以将此类用于请求。 Keep in mind, that abstract php classes can not be initialized directly.请记住,不能直接初始化抽象 php 类。 Same goes for abstract complex types in the wsdl. wsdl 中的抽象复杂类型也是如此。

Now we need the request element as a class.现在我们需要请求元素作为 class。 This is our parent element in our soap request.这是我们 soap 请求中的父元素。 The PlaceRequest element just has one property called request . PlaceRequest元素只有一个名为request的属性。 Since this element is a inheritation of HomeAffairsIDVRequestBase and this definition is abstract, wie have to use a type attribute later in the 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;
    }
}

Until now we have our data structure as PHP value objects.到目前为止,我们的数据结构为 PHP 值对象。 That 's all we need so far.到目前为止,这就是我们所需要的。 Now let us have a look on a possible request.现在让我们看看一个可能的请求。

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)
}

Since I don 't see the whole wsdl content, I can not say, how the request XML should look like.由于我没有看到整个 wsdl 内容,我不能说请求 XML 应该是什么样子。 It can happen, that the above shown ends up in a soap fault.上面显示的结果可能会导致 soap 故障。 In this case try the following example.在这种情况下,请尝试以下示例。

Change the type hint in the PlaceRequest class.更改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;
    }
}

After that create a new SoapVar instance with the $standard instance.之后,使用$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);

As an additional information you should always look at the send xml and the received xml to have a better overview on error handling.作为附加信息,您应该始终查看发送 xml 和接收 xml 以更好地了解错误处理。 We 've set the trace option when initializing the soap client.我们在初始化 soap 客户端时设置了trace选项。 This enables us to see, what the last request and the last response were.这使我们能够看到最后一个请求和最后一个响应是什么。

...
} catch (SoapFault $fault) {
    if ($client) {
        // get last request
        var_dump($client->__getLastRequest());

        // get last response
        var_dump($client->__getLastResponse());
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM