Zend PHP 5 Certification Study Guide (2014)

Web Services

Web services have given rise to a new way of thinking about data. They provide a way for any computer to exchange data with another, using the Web as a transport medium. Some web services are free—indeed, some companies offer free web services as a convenient way to allow third parties to extend their products and enrich their business models, while others charge for usage. Some are complex; others are simple. Regardless, one thing is certain: web services are changing the landscape of the Web.

According to the W3C, Web services “provide a standard means of interoperating between different software applications, running on a variety of platforms and/or frameworks.” For more from the W3C see http://www.w3.org/2002/ws/arch/. Web services are noted for being extensible and interoperable, and they are characterized by their use of XML to communicate between and among disparate systems. There are three popular types of Web services in use today: XML-RPC, SOAP (the successor to XML-RPC), and REST. PHP contains tools particularly suited for SOAP and REST Web services.

An exploration of SOAP and REST is well beyond the scope of this book—rather than glossing over these two complex protocols, we assume that you already have a good understanding of the way they work. There are many excellent books on both subjects, as well as a number of free resources on the Web dedicated to explaining how SOAP and REST Web services should be written.

REST

Representational State Transfer, or REST, is a Web service architectural style in which the focus is on the presence of resources in the system. Each resource must be identified by a global identifier—a URI. To access these resources, clients communicate with the REST service by HTTP, and the server responds with a representation of the resource. This representation is most often in the form of JSON, or XML, or sometimes even HTML. Services that use the REST architecture are referred to as RESTful services; those who use or provide RESTful services are sometimes humorously referred to as RESTafarians.

There are a number of RESTful Web services, the most popular of which thrive in the blogosphere. In a loose sense, Web sites that provide RSS and RDF feeds provide a RESTful service. Loosening the definition even further reveals that the entire Web itself may be thought of as following a RESTful architecture, with myriad resources and only a few actions to interact with them: GET, POST, PUT, HEAD, etc. In general, however, RESTful Web services allow standard GET requests to a resource and, in return, send an JSON or XML response. These services are not discoverable, so most providers have well-documented APIs.

Since RESTful Web services are not discoverable, do not provide a WSDL, and have no common interface for communication, there is no single REST class provided in PHP to access all RESTful services; however, most RESTful services respond with JSON data, which is easily parsed in PHP. For more on working with JSON, see the chapter on Data Formats and Types.

Typically, a basic HTTP client (e.g., Guzzle) or even streams and the json_decode() function are all we need to converse with a REST API—which probably accounts for their rise in popularity. For the server-side, a simple echo json_encode() is all that is needed. A common use for REST Web services is for client-side AJAX requests.

SOAP

SOAP was previously an acronym that stood for Simple Object Access Protocol; however, version 1.2 of the W3C standard for SOAP dropped the acronym altogether. So, technically, SOAP simply stands for…SOAP! SOAP is a powerful tool for communication between disparate systems, as it allows the definition and exchange of complex data types in both the request and response, as well as providing a mechanism for various messaging patterns, the most common of which is the Remote Procedure Call (RPC).

SOAP is intrinsically tied to XML, because all messages sent to and from a SOAP server are sent in a SOAP envelope that is an XML wrapper for data read and generated by the SOAP server. Creating the XML for this wrapper can be a tedious process; therefore, many tools and external PHP libraries have been created to aid developers in the cumbersome process of forming SOAP requests and reading SOAP server responses. PHP 5 simplifies this process with its SOAP extension, which makes the creation of both servers and clients very easy.

A SOAP Web service is defined by using a Web Service Description Language (WSDL, pronounced “whisdl”) document. This, in turn, is yet another XML document that describes the function calls made available by a Web service, as well as any specialized data types the service needs.

Accessing SOAP-Based Web Services

The SoapClient class provides what is essentially a one-stop solution for creating a SOAP client: all you really need to do is provide it with the path to a WSDL file, and it will automatically build a PHP-friendly interface that you can call directly from your scripts.

For example, consider the following SOAP request made to a search Web service:

Listing 14.1: A SOAP request

try {

  $client = new SoapClient(

    'http://api.example.org/search.wsdl'

  );

  $results = $client->doSearch(

    $key, $query, 0, 10, FALSE, '',  FALSE, ', ', ''

  );

  foreach ($results->resultElements as $result) {

     echo '<a href="' . htmlentities($result->URL) . '">';

     echo htmlentities($result->title, ENT_COMPAT, 'UTF-8');

     echo '</a><br/>';

  }

} catch (SoapFault $e) {

  echo $e->getMessage();

}

This creates a new SOAP client using the WSDL file provided by the server. SoapClient uses the WSDL file to construct an object mapped to the methods defined by the web service; thus, $client will now provide the method doSearch() and any other specified methods. In our example, the script invokes the doSearch() method to return a list of search results. If SoapClient encounters any problems, it will throw an exception, which we can trap as explained in the Errors and Exceptions chapter.

The constructor of the SOAPClient class also accepts, as an optional second parameter, an array of options that can alter its 'line-height:normal;background:#EEEEEE'>If you are accessing a SOAP service that does not have a WSDL file, it is possible to create a SOAP client in non-WSDL mode by passing a NULL value to the SoapClient constructor instead of to the location of the WSDL file. In this case, you will have to pass the URI to the Web service’s entry point as part of the second parameter.

Debugging

SoapClient provides special methods that make it possible to debug messages sent to and received from a SOAP server. These messages can be turned on by setting the trace option to 1 when instantiating a SOAP client object. This, in turn, will make it possible for you to access the raw SOAP headers and envelope bodies. Here’s an example:

Listing 14.2: Debugging a SOAP request

$client = new SoapClient(

    'http://api.example.org/search.wsdl', ['trace' => 1]

);

$results = $client->doSearch(

    $key, $query, 0, 10, FALSE, '', FALSE, ', ', ''

);

echo $client->__getLastRequestHeaders();

echo $client->__getLastRequest();

This will output something similar to the following (we trimmed down the text for the sake of conciseness):

POST /search HTTP/1.1

Host: api.example.org

Connection: Keep-Alive

User-Agent: PHP SOAP 0.1

Content-Type: text/xml; charset=utf-8

SOAPAction: "urn:SearchAction"

Content-Length: 900

<?xml version="1.0" encoding="UTF-8"?>

<SOAP-ENV:Envelope

  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"

  xmlns:ns1="urn:Search"

  xmlns:xsd="http://www.w3.org/2001/XMLSchema"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"

  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">

  <SOAP-ENV:Body>

    <ns1:doSearch>

      <key xsi:type="xsd:string">XXXXXXXXXX</key>

      <q xsi:type="xsd:string">PHP: Hypertext Preprocessor</q>

      <start xsi:type="xsd:int">0</start>

      <maxResults xsi:type="xsd:int">10</maxResults>

    </ns1:doSearch>

  </SOAP-ENV:Body>

</SOAP-ENV:Envelope>

Creating SOAP-Based Web Services

Just as SoapClient simplifies the task of building a Web service client, the SoapServer class performs all the background work of handling SOAP requests and responses. When creating a SOAP server, you simply start with a class that contains the methods you wish to make available to the public through a Web service and use it as the basis of a SoapServer instance.

For the remainder of this chapter, we will use this simple class for illustration purposes:

Listing 14.3: Simple SOAP server

class MySoapServer

{

    public function getMessage() {

        return 'Hello, World!';

    }

    public function addNumbers($num1, $num2) {

        return $num1 + $num2;

    }

}

When creating a SOAP server with SoapServer, you must decide whether your server will operate in WSDL or non-WSDL mode. At present, SoapServer will not automatically generate a WSDL file based on an existing PHP class, although this feature is planned for a future release. For now, you can either create your WSDL files manually—usually an incredibly tedious task—or there are tools that will generate them for you; you can also choose not to provide a WSDL file at all. For the sake of simplicity, our example SOAP server will operate in non-WSDL mode.

Once we have created the server, we need to inform it of the class that we want the web service to be based on. In this case, our SOAP server will use the MySoapServer class. Finally, to process incoming requests, call the handle() method:

$options = ['uri' => 'http://example.org/soap/server/'];

$server = new SoapServer(NULL, $options);

$server->setClass('MySoapServer');

$server->handle();

While this SOAP service works just fine in non-WSDL mode, it is important to note that a WSDL file can be helpful both for users of the service and for the SoapServer object itself. For users, a WSDL file helps expose the various methods and data types available. For the server, the WSDL file allows the mapping of different WSDL types to PHP classes, thus making the handling of complex data simpler.

The following example shows how a client might access the SOAP server described in this section. Notice how the client is able to access the getMessage() and addNumbers() methods of the MySoapServer class:

Listing 14.4: Client access to our simple SOAP server

$options = [

  'location' => 'http://example.org/soap/server/server.php',

  'uri'      => 'http://example.org/soap/server/'

];

$client = new SoapClient(NULL, $options);

echo $client->getMessage() . "\n";

echo $client->addNumbers(3, 5) . "\n";

Summary

If you have to work with SOAP, then PHP’s SOAP extension makes it as easy as possible—whereas REST is simple by design. The SOAP functionality is made possible thanks to PHP 5’s general advances in handling XML, so a good working knowledge of both is beneficial.

The reality, however, is that SOAP is unofficially dead, and REST has been crowned king. Most APIs you’ll use in practice will use REST.