您好,登录后才能下订单哦!
# PHP的SOAP方法怎么调用
## 一、SOAP协议基础概念
### 1.1 什么是SOAP协议
SOAP(Simple Object Access Protocol)简单对象访问协议是一种基于XML的通信协议,用于在Web服务之间交换结构化信息。它被设计用来在分布式环境中实现应用程序之间的通信,具有以下核心特点:
- **平台无关性**:可以在任何操作系统上运行
- **语言独立性**:支持多种编程语言实现
- **基于XML**:所有消息都采用XML格式编码
- **传输协议无关**:可通过HTTP、SMTP等多种协议传输
### 1.2 SOAP与REST的区别
| 特性 | SOAP | REST |
|-----------|-------------------------------|------------------------|
| 协议 | 严格定义的协议规范 | 架构风格,非正式协议 |
| 消息格式 | 仅XML | XML/JSON/纯文本等 |
| 传输协议 | HTTP/SMTP等 | 通常仅HTTP |
| 安全性 | WS-Security等内置安全标准 | 依赖HTTPS等传输层安全 |
| 性能 | 相对较低(XML解析开销大) | 相对较高 |
| 适用场景 | 企业级应用、高安全性要求的系统 | 移动应用、快速开发场景 |
### 1.3 SOAP消息结构剖析
一个完整的SOAP消息包含以下部分:
```xml
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<soap:Header>
<!-- 可选头部信息,如认证令牌 -->
</soap:Header>
<soap:Body>
<!-- 实际请求或响应内容 -->
<m:GetProductPrice xmlns:m="http://example.org/product">
<m:ProductID>12345</m:ProductID>
</m:GetProductPrice>
</soap:Body>
<soap:Fault>
<!-- 错误时出现 -->
</soap:Fault>
</soap:Envelope>
在大多数PHP环境中,SOAP扩展默认不启用。安装方法如下:
Linux环境(Ubuntu/Debian):
sudo apt-get install php-soap
sudo systemctl restart apache2
Windows环境:
1. 打开php.ini文件
2. 取消注释或添加:extension=soap
3. 重启Web服务器
创建测试脚本soap_test.php
:
<?php
phpinfo();
?>
在浏览器中访问该文件,搜索”soap”应能看到SOAP扩展的相关信息。
在php.ini中可以配置以下SOAP相关参数:
[soap]
; 是否启用WSDL缓存
soap.wsdl_cache_enabled=1
; WSDL缓存目录
soap.wsdl_cache_dir="/tmp"
; 缓存有效期(秒)
soap.wsdl_cache_ttl=86400
PHP提供了SoapClient
类用于创建SOAP客户端:
$client = new SoapClient(
"http://example.com/service.wsdl",
[
'trace' => 1, // 启用跟踪以便调试
'exceptions' => 1, // 抛出SOAP异常
'cache_wsdl' => WSDL_CACHE_NONE // 开发时禁用缓存
]
);
假设服务端提供了getUserInfo
方法:
try {
$response = $client->__soapCall('getUserInfo', [
['userId' => 123]
]);
// 或者直接调用
$response = $client->getUserInfo(['userId' => 123]);
print_r($response);
} catch (SoapFault $e) {
echo "SOAP Error: " . $e->getMessage();
}
当需要传递复杂对象时:
class User {
public $id;
public $name;
public $email;
}
$user = new User();
$user->id = 123;
$user->name = "John Doe";
$user->email = "john@example.com";
$response = $client->updateUser(['user' => $user]);
// 获取最后请求的XML
echo "Request: \n" . $client->__getLastRequest() . "\n";
// 获取最后响应的XML
echo "Response: \n" . $client->__getLastResponse() . "\n";
// 获取所有可用方法
print_r($client->__getFunctions());
// 获取类型信息
print_r($client->__getTypes());
class ProductService {
/**
* @param int $id
* @return float
*/
public function getPrice($id) {
// 实际业务逻辑
return 99.99;
}
}
$server = new SoapServer("service.wsdl");
$server->setClass("ProductService");
$server->handle();
可以使用工具如php-wsdl-creator
或手动编写:
<!-- service.wsdl -->
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://example.com/product">
<types>
<xsd:schema>
<xsd:element name="getPriceRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="id" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="getPriceResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="price" type="xsd:float"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
<message name="getPriceInput">
<part name="parameters" element="tns:getPriceRequest"/>
</message>
<message name="getPriceOutput">
<part name="parameters" element="tns:getPriceResponse"/>
</message>
<portType name="ProductPortType">
<operation name="getPrice">
<input message="tns:getPriceInput"/>
<output message="tns:getPriceOutput"/>
</operation>
</portType>
<binding name="ProductBinding" type="tns:ProductPortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getPrice">
<soap:operation soapAction="http://example.com/getPrice"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="ProductService">
<port name="ProductPort" binding="tns:ProductBinding">
<soap:address location="http://example.com/soap_server.php"/>
</port>
</service>
</definitions>
class SecureService {
private $validTokens = ['12345', '67890'];
public function __construct() {
$this->checkAuth();
}
private function checkAuth() {
$headers = getallheaders();
if (!isset($headers['Authorization'])) {
throw new SoapFault('Server', 'Unauthorized');
}
$token = str_replace('Bearer ', '', $headers['Authorization']);
if (!in_array($token, $this->validTokens)) {
throw new SoapFault('Server', 'Invalid token');
}
}
public function sensitiveOperation() {
return "Secret data";
}
}
$server = new SoapServer("secure.wsdl");
$server->setClass("SecureService");
$server->handle();
// 客户端发送附件
$client = new SoapClient('service.wsdl', [
'stream_context' => stream_context_create([
'http' => [
'header' => 'Content-Type: application/xop+xml'
]
]),
'features' => SOAP_SINGLE_ELEMENT_ARRAYS
]);
// 服务端接收附件
if (isset($HTTP_RAW_POST_DATA)) {
$data = $HTTP_RAW_POST_DATA;
} else {
$data = file_get_contents('php://input');
}
“Could not connect to host”:
“Function not found”:
“Invalid XML”:
// 客户端代码
$weather = new SoapClient(
"http://www.webservicex.net/globalweather.asmx?WSDL",
['trace' => 1]
);
try {
$response = $weather->GetWeather([
'CityName' => 'New York',
'CountryName' => 'United States'
]);
echo "Weather Info: \n";
print_r($response);
} catch (SoapFault $e) {
echo "Error: " . $e->getMessage();
echo "\nRequest: " . $weather->__getLastRequest();
}
虽然SOAP仍在许多企业系统中使用,但RESTful API已成为主流。考虑以下场景选择技术:
选择SOAP:
选择REST:
新兴技术如gRPC也提供了强大的跨语言服务调用能力,可以作为现代替代方案。
PHP的SOAP扩展提供了完整的Web服务实现方案,虽然学习曲线较陡,但在特定场景下仍是不可或缺的技术。掌握SOAP开发需要理解XML、WSDL等底层技术,但一旦掌握,可以轻松集成各种企业级系统。建议开发者在实际项目中根据需求选择合适的Web服务技术,平衡开发效率与系统需求。
注意:本文示例代码需要根据实际环境调整,部分Web服务可能需要注册或认证才能使用。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。