使用 SOAP API
SOAP(簡單訪問物件協議)是基於 XML 的,就像 XML-RPC 一樣,是祖先,檔名為 WSDL ,用於描述要公開的方法。
該協議通常基於 SOAP-Enveloppe , SOAP-Body 和 SOAP-Header ,資料被包含在一個結構中,並被解釋為來自不同語言的相同方式。
有關更多資訊,請參閱: wiki 上的 SOAP
如上所述,描述 Web 服務最重要的是 WSDL 檔案,請參閱: wiki 上的 WSDL 說明
這項工作的基礎是定義 SOAP API 上公開的內容,你的類和業務流程將由基本的 PHP SOAPServer 類自動處理。你還需要程式碼!
讓我們看看檔案是如何構造的:
- 服務:設定 API URI 以及將關聯的內容。
- 繫結:它定義與服務關聯的操作
- 操作:你希望向 Web 公開的一些方法
- PortTypes:定義查詢和響應
- 請求和響應:你期望輸入和輸出
- 訊息:你對每個 IO 的期望(引數)形式,它們可以是簡單的(字串,整數,浮點…)或複雜型別(結構化格式)
有了這些基本資訊,你就可以實現所需的所有 API。
想象一下,你想要建立一個 SOAP api 來管理本地資料庫上的 StackOverFlower(User)
。
讓我們舉個例子吧!
安裝 Web 伺服器,Php cli,Composer,Symfony 2.8,建立一個新的 BundleExampleBundle
並構建如上所述的模式。
在我們開始構建業務邏輯之前,我們必須知道控制器的公開內容。這項工作是通過使用 WSDL 完成的。這是一個很好的 WSDL 語法示例:
<definitions name="StackOverFlowerService"
targetNamespace="http://example/soap/stackoverflower.wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://example/soap/stackoverflower.wsdl"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<message name="NewRequest">
<part name="name" type="xsd:string"/>
</message>
<message name="NewResponse">
<part name="status" type="xsd:string"/>
</message>
<message name="getListRequest"></message>
<message name="getListResponse">
<part name="list" type="xsd:string"/>
</message>
<message name="editRequest">
<part name="id" type="xsd:string"/>
<part name="name" type="xsd:string"/>
</message>
<message name="editResponse">
<part name="status" type="xsd:string"/>
</message>
<message name="deleteRequest">
<part name="id" type="xsd:string"/>
</message>
<message name="deleteResponse">
<part name="status" type="xsd:string"/>
</message>
<portType name="StackOverFlower_PortType">
<operation name="newStack">
<input message="tns:NewRequest"/>
<output message="tns:NewResponse"/>
</operation>
<operation name="getList">
<input message="tns:getListRequest"/>
<output message="tns:getListResponse"/>
</operation>
<operation name="edit">
<input message="tns:editRequest"/>
<output message="tns:editResponse"/>
</operation>
<operation name="delete">
<input message="tns:deleteRequest"/>
<output message="tns:deleteResponse"/>
</operation>
</portType>
<binding name="StackOverFlower_Binding" type="tns:StackOverFlower_PortType">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="newStack">
<soap:operation soapAction="newStack"/>
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:example:new"
use="encoded"/>
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:example:new"
use="encoded"/>
</output>
</operation>
<operation name="getList">
<soap:operation soapAction="getList"/>
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:example:get-list"
use="encoded"/>
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:example:get-list"
use="encoded"/>
</output>
</operation>
<operation name="edit">
<soap:operation soapAction="edit"/>
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:example:edit"
use="encoded"/>
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:example:edit"
use="encoded"/>
</output>
</operation>
<operation name="delete">
<soap:operation soapAction="delete"/>
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:example:delete"
use="encoded"/>
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:example:delete"
use="encoded"/>
</output>
</operation>
</binding>
<service name="StackOverFlower_Service">
<documentation>Description File of StackOverFlowerService</documentation>
<port binding="tns:StackOverFlower_Binding" name="StackOverFlower_Port">
<soap:address
location="http://example/stackoverflower/" />
</port>
</service>
</definitions>
我們必須在你的 web symfony 目錄中(在 soap 子目錄中,並將其命名為“stackoverflower.wsdl”)。
從 WSDl 示例中獲得靈感。你可以使用 Online WSDl Validator 對其進行驗證
在此之後,我們可以從 SOAP Symfony 2.8 Doc 啟發我們的基本服務和控制器。
服務,由 PHP SOAPServer 處理:
#src\ExampleBundle\Services\StackOverFlowerService.php
namespace ExampleBundle\Services;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use ExampleBundle\Entity\StackOverFlower;
class StackOverFlowerService
{
private $em;
private $stackoverflower;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function newStack($name)
{
$stackoverflower = new StackOverFlower();
$stackoverflower->setName($name);
$this->em->persist($stackoverflower);
$this->em->flush();
return "ok";
}
public function getList()
{
$stackoverflowers = $this->em->getRepository("ExampleBundle:StackOverFlower")->findAll();
$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new ObjectNormalizer());
$serializer = new Serializer($normalizers, $encoders);
return $serializer->serialize($stackoverflowers, 'json');
}
public function edit($id, $name)
{
$stackoverflower = $this->em->getRepository("ExampleBundle:StackOverFlower")->findOneById($id);
$stackoverflower->setName($name);
$this->em->persist($stackoverflower);
$this->em->flush();
return "ok";
}
public function delete($id)
{
$stackoverflower = $this->em->getRepository("ExampleBundle:StackOverFlower")->findOneById($id);
$this->em->remove($stackoverflower);
$this->em->flush();
return "ok";
}
}
配置此服務:
#src\ExampleBundle\Resources\config\services.yml
services:
stackoverflower_service:
class: ExampleBundle\Services\StackOverFlowerService
arguments: [@doctrine.orm.entity_manager]
如你所見,我們將 Doctrine Entity Manger 注入依賴項,因為我們必須將它用於 CRUD StackOverFlower 物件。
控制器,公開服務物件:
#src\ExampleBundle\Controller\StackOverFlowerController.php
namespace ExampleBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class StackOverFlowerController extends Controller
{
public function indexAction()
{
ini_set("soap.wsdl_cache_enabled", "0");
$options = array(
'uri' => 'http://example/app_dev.php/soap',
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => true
);
$server = new \SoapServer(dirname(__FILE__).'/../../../**web/soap/stackoverflower.wsdl**', $options);
$server->setObject($this->get('stackoverflower_service'));
$response = new Response();
$response->headers->set('Content-Type', 'text/xml; charset=utf-8');
ob_start();
$server->handle();
$response->setContent(ob_get_clean());
return $response;
}
}
要了解有關服務的更多資訊,請參閱: Symfony doc 上的服務容器
路線 :
example_soap:
path: /soap
defaults: { _controller: ExampleBundle:StackOverFlower:index }
基本的 Twig 模板:
#src\ExampleBundle\Resources\views\Soap\default.html.twig
{% if status is defined %}
{{ status }}
{% else %}
{{ list }}
{% endif %}
我們用 Symfony 2.8 建立了第一個 SOAP API!
在你暴露它之前,我們必須測試!!
在 StackOverFlowerController 中,新增:
public function testNewAction(Request $request)
{
$service = $this->get('stackoverflower_service');
$result = $service->newStack($request->query->get('name'));
return $this->render('ExampleBundle:Soap:default.html.twig', array('status' => $result));
}
public function testEditAction(Request $request)
{
$service = $this->get('stackoverflower_service');
$result = $service->edit($request->query->get('id'), $request->query->get('name'));
return $this->render('ExampleBundle:Soap:default.html.twig', array('status' => $result));
}
public function testGetListAction(Request $request)
{
$service = $this->get('stackoverflower_service');
$result = $service->getList();
return $this->render('ExampleBundle:Soap:default.html.twig', array('list' => $result));
}
public function testDeleteAction(Request $request)
{
$service = $this->get('stackoverflower_service');
$result = $service->delete($request->query->get('id'));
return $this->render('ExampleBundle:Soap:default.html.twig', array('list' => $result));
}
// To test this from an another server, you can type this :
// $client = new \SoapClient("http://example/app_dev.php/soap?wsdl", array("trace" => 1, "exception" => 1));
// $result = $client->newStack($request->query->get('name'));
// print_r($result);
路線:
test_new:
path: /stackoverflower/new
defaults: { _controller: ExampleBundle:StackOverFlower:testNew }
test_edit:
path: /stackoverflower/edit
defaults: { _controller: ExampleBundle:StackOverFlower:testEdit }
test_get_list:
path: /stackoverflower/get-list
defaults: { _controller: ExampleBundle:StackOverFlower:testGetList }
test_delete:
path: /stackoverflower/delete
defaults: { _controller: ExampleBundle:StackOverFlower:testDelete }
你可以在瀏覽器中輸入:
這是使用 SOAP 的非安全 API 的一個非常基本的示例,我可以稍後在 api 金鑰身份驗證後面做一個安全示例的示例。
所有人……
馬蒂厄