As with the SOAP client, we can use the PHP SOAP extension to implement a SOAP server. The most difficult part of the implementation will be generating the WSDL from the API class. We do not cover that process here as there are a number of good WSDL generators available.
Application\Web\Soap\ProspectsApi class that allows us to create, read, update, and delete the prospects table:namespace Application\Web\Soap;
use PDO;
class ProspectsApi
{
protected $registerKeys;
protected $pdo;
public function __construct($pdo, $registeredKeys)
{
$this->pdo = $pdo;
$this->registeredKeys = $registeredKeys;
}
}put(), get(), post(), and delete(). These, in turn, call methods that generate SQL requests that are executed from a PDO instance. An example for get() is as follows:public function get(array $request, array $response)
{
if (!$this->authenticate($request)) return FALSE;
$result = array();
$id = $request[self::ID_FIELD] ?? 0;
$email = $request[self::EMAIL_FIELD] ?? 0;
if ($id > 0) {
$result = $this->fetchById($id);
$response[self::ID_FIELD] = $id;
} elseif ($email) {
$result = $this->fetchByEmail($email);
$response[self::ID_FIELD] = $result[self::ID_FIELD] ?? 0;
} else {
$limit = $request[self::LIMIT_FIELD]
?? self::DEFAULT_LIMIT;
$offset = $request[self::OFFSET_FIELD]
?? self::DEFAULT_OFFSET;
$result = [];
foreach ($this->fetchAll($limit, $offset) as $row) {
$result[] = $row;
}
}
$response = $this->processResponse(
$result, $response, self::SUCCESS, self::ERROR);
return $response;
}
protected function processResponse($result, $response,
$success_code, $error_code)
{
if ($result) {
$response['data'] = $result;
$response['code'] = $success_code;
$response['status'] = self::STATUS_200;
} else {
$response['data'] = FALSE;
$response['code'] = self::ERROR_NOT_FOUND;
$response['status'] = self::STATUS_500;
}
return $response;
}phpDocumentor tags before the methods that will be published. In our example, the two arguments are both arrays. Here is the full WSDL for the API discussed earlier:<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:tns="php7cookbook" targetNamespace="php7cookbook" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<wsdl:message name="getSoapIn">
<wsdl:part name="request" type="tns:array" />
<wsdl:part name="response" type="tns:array" />
</wsdl:message>
<wsdl:message name="getSoapOut">
<wsdl:part name="return" type="tns:array" />
</wsdl:message>
<!—some nodes removed to conserve space -->
<wsdl:portType name="CustomerApiSoap">
<!—some nodes removed to conserve space -->
<wsdl:binding name="CustomerApiSoap" type="tns:CustomerApiSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc" />
<wsdl:operation name="get">
<soap:operation soapAction="php7cookbook#get" />
<wsdl:input>
<soap:body use="encoded" encodingStyle= "http://schemas.xmlsoap.org/soap/encoding/" namespace="php7cookbook" parts="request response" />
</wsdl:input>
<wsdl:output>
<soap:body use="encoded" encodingStyle= "http://schemas.xmlsoap.org/soap/encoding/" namespace="php7cookbook" parts="return" />
</wsdl:output>
</wsdl:operation>
<!—some nodes removed to conserve space -->
</wsdl:binding>
<wsdl:service name="CustomerApi">
<wsdl:port name="CustomerApiSoap" binding="tns:CustomerApiSoap">
<soap:address location="http://localhost:8080/" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>chap_07_simple_soap_server.php file, which will execute the SOAP server. Start by defining the location of the WSDL and any other necessary files (in this case, one for database configuration). If the wsdl parameter is set, deliver the WSDL rather than attempting to process the request. In this example, we use a simple API key to authenticate requests. We then create a SOAP server instance, assign an instance of our API class, and run handle():<?php
define('DB_CONFIG_FILE', '/../config/db.config.php');
define('WSDL_FILENAME', __DIR__ . '/chap_07_wsdl.xml');
if (isset($_GET['wsdl'])) {
readfile(WSDL_FILENAME);
exit;
}
$apiKey = include __DIR__ . '/api_key.php';
require __DIR__ . '/../Application/Web/Soap/ProspectsApi.php';
require __DIR__ . '/../Application/Database/Connection.php';
use Application\Database\Connection;
use Application\Web\Soap\ProspectsApi;
$connection = new Application\Database\Connection(
include __DIR__ . DB_CONFIG_FILE);
$api = new Application\Web\Soap\ProspectsApi(
$connection->pdo, [$apiKey]);
$server = new SoapServer(WSDL_FILENAME);
$server->setObject($api);
echo $server->handle();You can easily test this recipe by first creating your target API class, and then generating a WSDL. You can then use the built-in PHP webserver to deliver the SOAP service with this command:
php -S localhost:8080 chap_07_simple_soap_server.php
You can then use the SOAP client discussed in the previous recipe to make a call to test the SOAP service:
<?php
define('WSDL_URL', 'http://localhost:8080?wsdl=1');
$clientKey = include __DIR__ . '/api_key.php';
try {
$client = new SoapClient(WSDL_URL);
$response = [];
$email = some_email_generated_by_test;
$email = 'test5393@unlikelysource.com';
echo "\nGet Prospect Info for Email: " . $email . "\n";
$request = ['token' => $clientKey, 'email' => $email];
$result = $client->get($request,$response);
var_dump($result);
} catch (SoapFault $e) {
echo 'ERROR' . PHP_EOL;
echo $e->getMessage() . PHP_EOL;
} catch (Throwable $e) {
echo 'ERROR' . PHP_EOL;
echo $e->getMessage() . PHP_EOL;
} finally {
echo $client->__getLastResponse() . PHP_EOL;
}Here is the output for email address test5393@unlikelysource.com:

A simple Google search for WSDL generators for PHP came back with easily a dozen results. The one used to generate the WSDL for the ProspectsApi class was based on https://code.google.com/archive/p/php-wsdl-creator/. For more information on phpDocumentor, refer to the page at https://www.phpdoc.org/.