Using PHP's SDO and SCA extensions

PHP Web services made easy

The PHP SCA extension is a Web service implementation for PHP that allows developers to easily create SCA (Service Component Architecture) components through PHP annotations on a PHP class. Data can also be represented using Service Data Objects (SDO). This article shows developers how to create a Web service using the PHP SCA extension, and how the Web service data is represented using SDOs.

Tyler Anderson (tyleranderson5@yahoo.com), Freelance writer

Tyler Anderson graduated with a degree in Computer Science from Brigham Young University in 2004 and is currently in his last semester as a Master of Science student in Computer Engineering. In the past, he worked as a database programmer for DPMG.COM, and he is currently an engineer for Stexar Corp., based in Beaverton, Oregon.



19 June 2007

Also available in Japanese

Introduction

Web services through deployment of Service Oriented Architectures (SOA) is increasingly more common. An SOA is several Web services working together for a common goal, and the new PHP SCA extension has been developed to lower the barrier for PHP developers to develop easily maintained Web services. You see, before PHP SCA came along, Web services development in PHP was more difficult, having no solid WSDL service support. In other enterprise languages, like the Java™ language, there are numerous methods for creating Web services, and thanks to the PHP SCA SDO extensions, better Web services support has been brought to PHP developers.

The PHP SDO module allows you to handle data in PHP in such a way that code is agnostic to the source of the data, be it flat XML data or a relational database. This helps keep your code neat and simple, and also allows you to change the source from which you ultimately pull data from for your application. Thus, data is created using an SDO, automatically translated to XML during transit to the Web service, recreated into another SDO on the receiving end for you to conveniently read and manipulate in your Web service, and vice versa with the client.

Using the PHP SCA extension, you'll learn in this article how to create a weather Web service, while using the PHP SDO extension to handle and incorporate data into your Web application. The Web service will take hardcoded data from a client you create and the weather service will return hardcoded data. You'll also see how to extract auto-generated WSDL from the Web service you create, and test your Web service using the client.


Installing the PHP SDO/SCA extensions

In order to use the PHP SDO and SCA extensions, you're going to have to install them using the pecl command line tool. Go to your PHP directory (c:\apps\wamp\php in the author's case), and type (for Windows® systems using Wamp Server 1.7.1a -- a for Apache version): pecl install -B SCA_SDO.

The -B flag stands for nobuild, essentially telling pecl not to build the C extensions. In UNIX®/Linux® systems, you need to leave off the -B flag: pecl install SCA_SDO.

For Windows users, you need to get the latest php_sdo.dll from pecl4win.php.net (if your build came with a php_sdo.dll file, it may be outdated and not work). If you're running Wamp Server 1.7.1a, then grab the one for php-5.2.1, and place it in your php/ext directory. Lastly, add the following line to your php.ini file: extension=php_sdo.dll.

For UNIX/Linux users, pecl built the sdo library for you, sdo.so. Add it as an extension to your php.ini file as follows: extension=sdo.so.

An finally, make sure the include path containing your php and php/PEAR directories are in the include_path directive in your php.ini file, so that when you include the appropriate SCA files later in the article the PHP processor will know where to look for the libraries. The contents of the author's are shown here: include_path = ".;c:\apps\wamp\php\includes;c:\apps\wamp\php;C:\apps\wamp\php\PEAR".

Both the PHP SCA and SDO extensions should now be installed on your system. Note that the PHP SCA module is marked as experimental and may change without notice in a future release of PHP.

Moving on, you'll begin development of the Web service.


Developing a Web service PHP class

Now you get to build a class that will comprise the Web service. This article will show off the features of PHP's SCA and SDO extensions using a simple, hardcoded weather service. You'll use an SDO to send which areas you wish to send to the weather service to return temperatures on. The Web service will then print out the areas received, and then use an SDO to return pairs of areas and associated temperatures. First, you'll lay down the infrastructure for the Weatherservice class.

The weather service

First, you're going to create a class with a function, and then later you'll define and annotate it. Begin with the class definition in Listing 1.

Listing 1. The WeatherService class
<?php

class WeatherService {

    function getTemperature($Areas) {
    }
}

?>

Here you have the WeatherService class and a function, getTemperature, that gets the areas that users wish to retrieve the temperatures of passed into it as a parameter. You'll define the function next.

Using SDOs

SDOs are objects that allow you to easily handle XML data without needing to know from where it came. Define the function, as shown in Listing 2.

Listing 2. Defining the getTemperature function
<?php

class WeatherService {

    function getTemperature($Areas) {
        echo "Area list received from client:<br>";
        foreach($Areas->area as $area)
            echo $area->state . "<br>";
        echo "<br>";

        $Temperatures = SCA::createDataObject('http://Weather',
                                              'Temperatures');
        $Pair = $Temperatures->createDataObject('entry');
        $Pair->state = 'CA';
        $Pair->temperature = 65;
        $Pair = $Temperatures->createDataObject('entry');
        $Pair->state = 'UT';
        $Pair->temperature = 105;
        $Pair = $Temperatures->createDataObject('entry');
        $Pair->state = 'ND';
        $Pair->temperature = -20;
        return $Temperatures;
    }
}

?>

In Listing 2 you see the areas come into the function and get printed out. You'll learn more about the schema of both the areas and temperatures data structures later. For now, just notice how each is being accessed, and also how the $Temperatures object is created. Adding an entry to the list of temperatures simply requires that a new object be created, automatically adding it as a child to the parent. The state and temperature are then variables of each of the three new objects that you create.

Next, annotate the class with PHP annotations, effectively giving the PHP SCA extension details about this new Web service.

Adding PHP annotations

The PHP annotations are essential to completing the Web service, and are what communicates to the PHP SCA module that this class is indeed a Web service. See how the annotations are done in Listing 3.

Listing 3. Annotating the Web service class
<?php

include "SCA/SCA.php";

/**
 * @service
 * @binding.soap
 *
 * @types http://Weather AreasTypes.xsd
 * @types http://Weather TemperaturesTypes.xsd
 */
class WeatherService {

    /**
     * @param Areas $Areas http://Weather
     * @return Temperatures http://Weather
     */
    function getTemperature($Areas) {
        echo "Area list received from client:<br>";
...
        return $Temperatures;
    }
}

?>

The most important annotation is the first one, @service, which designates this class as a Web service. The @binding.soap annotation tells PHP SCA to use SOAP bindings for the Web service. The next two are @types annotations, which bring in the Areas and Temperatures data structures you already used in the getTemperature method of the Web service. These annotations basically tell PHP SCA where to get the schemas for the two SDO data structures you wish to use. The @param annotation on the function specifies the type of the parameter passed in, and $Areas is of type Areas with namespace http://Weather (the Areas type is then matched to the Areas type referenced in the @types annotation). The @return does the same thing as the @param annotation, except that it specifies that the parameter is the return value. Note that you must also include "SCA/SCA.php." Doing so causes the PHP SCA module to recognize the class and its annotations as a Web service.

In the next section you'll define the schemas, as referenced in the @types annotations.


Defining schemas

Now that the Web service is completely defined, you're going to define the two schemas referenced in Listing 3, beginning with the Areas schema.

Areas schema

You should remember this data structure the $Areas variable used in Listing 2. The schema, shown in Listing 4, tells PHP SCA SDO the inner parts to this variable and how to use it in an SDO.

Listing 4: The Areas schema
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://Weather" 
           elementFormDefault="qualified">

  <xs:complexType name="StateType">
    <xs:sequence>
      <xs:element name="state" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="Areas">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="area" type="ns1:StateType" 
                    maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>

See how the namespace also matches up with the namespace in the corresponding @types annotation in Listing 3. The top-level element, Areas, can contain an unbounded series of areas of type StateType, essentially a string. And if you remember from Listing 2, that's exactly the structure being used: Iterating over a list of area, and displaying its state to the screen. Next you'll define the Temperatures schema.


Temperatures schema

The Temperatures data structure also was used in Listing 2 and Listing 3, and the concepts of it greatly mirror that of the previous Areas schema. Take a look at it in Listing 5.

Listing 5. The Temperatures schema
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://Weather"
           elementFormDefault="qualified">

  <xs:complexType name="PairType">
    <xs:sequence>
      <xs:element name="state" type="xs:string"/>
      <xs:element name="temperature" type="xs:float"/>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="Temperatures">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="entry" type="ns1:PairType" 
                    maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>

See how the namespace also matches that shown in the corresponding @types annotation in Listing 3. You should also recognize the structure and how you constructed a new Temperatures data type in Listing 2. Remember, you first created a $Temperatures variable, and created three children elements: entry, and set the state and temperature variables, respectively.

In developing the client you'll see how to construct an Areas data type, and display the Temperatures data type to the browser.


Developing a client

Now all you need is a client to test it out! A simple client will do, which is what you'll learn how to code here, and how to send and receive your request in SDOs.

Creating the request

Creating the request is nearly the opposite of what you did in the Web service where you dismantled the request and created a response. In the next couple of sections you'll create a request and then dismantle the response. See how the request is created in Listing 6.

Listing 6. Creating the request
<?php

include "SCA/SCA.php";

$weather = SCA::getService('WeatherService.php');

$Areas = $weather->createDataObject('http://Weather',
                                    'Areas');
$area = $Areas->createDataObject('area');
$area->state = 'CA';
$area = $Areas->createDataObject('area');
$area->state = 'UT';
$area = $Areas->createDataObject('area');
$area->state = 'ND';
...

Again, as you did in the Web service, include SCA/SCA.php. Note how easy it is to create the Web service. You've created it in a single line of code, with the call to SCA::getService. Note that here you've created a local Web service as the Web service is a local PHP file. See Resources for more information on other ways to create Web services, including remote ones. Moving on, you create the request, the $Areas SDO, and add three states to it: CA, UT and ND.

Next you'll send and process the request.

Sending and receiving the request

After creating the request, you can go ahead and pass it to the Web service, as shown in Listing 7.

Listing 7. Sending and receiving the request
...
$Temperatures = $weather->getTemperature($Areas);

echo "Received temperatures from Web service:<br>";
foreach($Temperatures->entry as $Pair)
    echo $Pair->state . ": " . $Pair->temperature . "<br>";

?>

Here the request is made, and the response is stored in $Temperatures (the same object you constructed in the Web service back in Listing 2). Lastly, you dismantle the response and display it to the user, except this time instead of just displaying the state you have two variables to display, the state and the associated temperature.

That does it. Next you'll verify that everything works!


Deploy and test

It is now time for testing. There's nothing special when it comes to deploying this slick PHP Web service. In fact, it's already up and running as long as your Web server's running, as you'll see next.

Viewing created WSDL

See the WSDL for yourself by pulling up a browser, and entering (on the author's system): http://localhost/WeatherService.php?wsdl.

You'll then see the WSDL of your Web service (see Listing 8), without even creating WSDL in the first place.

Listing 8. Auto-generated WSDL
<definitions targetNamespace="http://WeatherService">

  <types>
    <xs:schema targetNamespace="http://WeatherService" 
                 elementFormDefault="qualified">
      <xs:import schemaLocation="AreasTypes.xsd" 
                 namespace="http://Weather"/>
      <xs:import schemaLocation="TemperaturesTypes.xsd" 
                 namespace="http://Weather"/>

      <xs:element name="getTemperature">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="Areas" type="ns1:Areas" 
                        nillable="true"/>
          </xs:sequence>
        </xs:complexType>
       /xs:element>

      <xs:element name="getTemperatureResponse">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="getTemperatureReturn"
                        type="ns1:Temperatures" 
                        nillable="true"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
  </types>

  <message name="getTemperatureRequest">
    <part name="getTemperatureRequest" element="tns2:getTemperature"/>
  </message>

  <message name="getTemperatureResponse">
    <part name="return" element="tns2:getTemperatureResponse"/>
  </message>

  <portType name="WeatherServicePortType">
    <operation name="getTemperature">
      <input message="tns2:getTemperatureRequest"/>
      <output message="tns2:getTemperatureResponse"/>
    </operation>
  </portType>

  <binding name="WeatherServiceBinding" 
           type="tns2:WeatherServicePortType">
    <operation name="getTemperature">
      <input>
        <tns3:body xsi:type="tns3:tBody" use="literal"/>
      </input>
      <output>
        <tns3:body xsi:type="tns3:tBody" use="literal"/>
      </output>
      <tns3:operation xsi:type="tns3:tOperation" soapAction=""/>
    </operation>
    <tns3:binding xsi:type="tns3:tBinding" 
                  transport="http://schemas.xmlsoap.org/soap/http" 
                  style="document"/>
  </binding>

  <service name="WeatherServiceService">
    <port name="WeatherServicePort" 
            binding="tns2:WeatherServiceBinding">
      <tns3:address xsi:type="tns3:tAddress" 
                    location="http://localhost/WeatherService.php"/>
    </port>
  </service>
</definitions>

<!--
    this line identifies this file as WSDL generated by SCA for PHP. Do not remove 
  -->

You can feed this WSDL into other Web services generators for other languages, such as Java, or for another one of your PHP Web services that comprise your deployed SOA. Notice the two import statements in Listing 8. These lines import the two schemas that you specified in the @types annotations in the WeatherService class back in Listing 3, into the above defined WSDL (see Listing 8). The rest of the first block of lines in bold font are the wrapper data types for the request and response, getTemperature and getTemperatureResponse, respectively. And the last line to note is the location attribute of the address element that specifies the location of the Web service, exactly where you pulled the WSDL from.

Next you'll run the client, and see what comes of it!


Sending and receiving the request

All right, you should be a PHP SCA SDO pro by now. This may be a little tricky at first, but once you get a feel for it, it's simple, and you may wonder why you'd need any other language for your SOA deployment needs ever again.

OK, open up a browser to the client (http://localhost/client.php), and take a look at the results in Figure 1.

Figure 1. Results of running the client
results of running the client

It worked! In your client code you sent CA, UT, and ND, and successfully received and displayed them in the server code. You then also sent CA, UT, and ND with 65, 105, and -20 as the temperatures, respectively, as a response from the Web service, and successfully displayed the correct values back in the client.

Excellent! You're finished. Now you can brag to all your friends about how easy it is for you to create Web services.


Summary

If you're a hardcore PHP developer you've probably never seen a Web service created like that before. It's like the ease of Web services Java developers are familiar with has finally come to PHP, and it's a great thing. In this article, you:

  • Successfully installed the PHP SCA and SDO extensions
  • Created and annotated a Web service class
  • Created a simple client, and were successful at testing your new Web service
  • Successfully used and incorporated an SDO into your client and Web service

Download

DescriptionNameSize
Sample codesdo_sca_source.zip3KB

Resources

Learn

Get products and technologies

  • Download the PHP SCA and SDO extensions straight from pecl.php.net.

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=232252
ArticleTitle=Using PHP's SDO and SCA extensions
publish-date=06192007