为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

PHP
慕勒3428872 2023-04-21 15:15:35
我最近开始使用 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>注意:我无法编辑 wsdl。
查看完整描述

1 回答

?
慕婉清6462132

TA贡献1804条经验 获得超2个赞

您可以从 wsdl 读取复杂类型定义作为 php 类定义。每个复杂类型都是一个 php 值对象。抽象复杂类型是抽象的值对象,可以从中继承。


由于我们定义了复杂类型,我们可以构建我们的 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;

    }

}

这是我们作为抽象 php 类的第一个抽象复杂类型定义HomeAffairsIDVRequestBase。如您所见,抽象类具有所有属性,这些属性在 wsdl 文件中为此复杂类型定义。除此之外,我们还有 getter 和 setter 方法来更好地处理类属性。


当我们查看 for 的定义时HomeAffairsIDVStandardRequest,我们可以看到它继承自HomeAffairsIDVRequest. 考虑到这一点,我们必须编写更多的 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

{


}

由于其中一种复杂类型HomeAffairsIDVStandardRequest不是HomeAffairsIDVAdvancedRequest抽象的,因此可以将此类用于请求。请记住,抽象 php 类不能直接初始化。wsdl 中的抽象复杂类型也是如此。


现在我们需要将请求元素作为一个类。这是我们 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 PlaceRequest 

{

    protected SoapVar $request;


    public function getRequest(): SoapVar

    {

        return $this->request;

    }


    public function setRequest(SoapVar $request): self

    {

        $this->request = $request;

        return $this;

    }

}

之后使用该实例创建一个新的 SoapVar 实例$standard。


// 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,以便更好地了解错误处理。我们trace在初始化 soap 客户端时设置了选项。这使我们能够看到最后的请求和最后的响应是什么。


...

} catch (SoapFault $fault) {

    if ($client) {

        // get last request

        var_dump($client->__getLastRequest());


        // get last response

        var_dump($client->__getLastResponse());

    }

}


查看完整回答
反对 回复 2023-04-21
  • 1 回答
  • 0 关注
  • 99 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信