September 20th, 2008SOA Way of Writing PHP

Traditional way of Writing PHP
Let me draw a component diagram of a typical traditional(conventional) PHP web application.MVC Architecture Model

With this design you get the advantages of the client-server architecture and the MVC design pattern.

Advantages of the Traditional Approach

  • You can connect to the server from anywhere that has the connectivity to the centralized server. Say you process purchase orders in your application. Sails agents, customers around the world can connect to the application from their computers and do purchase orders. (Because of the Client-Server Architecture)client-server architecture
  • Doing Changes to the inside of the components (Model, View and Controller) are relatively easy , because of the separation of the logics. But if changes affect to inter-communication of each component then it become harder because of the low granularity. (check disadvantages)

Are their any disadvantages of this approach?
Yes. There are plenty of them. Actually it is lot more than the advantages list.

Disadvantages of the Traditional Approach

  • More Server load: The only server is responsible for maintenance of all the components. And there is no straight forward way to distribute these components in a network.
  • No Interoperability: Can I replace the PHP Presentation layer with a .NET, C, Java Desktop Application with this design? No. PHP components (Model, View, Controller) are communicated in PHP code level through php function calls or may be through PHP object interactions, If you want to integrate .NET/Java to replace one component, you have to change all these function calls, object passings with each components.
    non-interoperability
  • Fine Grained Interfaces: Even when I want to replace some component with another PHP implementation, it is still very difficult to integrate to the running system because of the fine-grained interfaces (Lot of small operations) used in the inter-component communication.
    Mostly this issue comes when integrating new business component to existing business logic within the controller logic. The below is just a figure to demonstrate what is meant by fine-grained interface.
    fine-grained-services
    This causes the application to be slow (more message exchange => more time on the wire =&t; lesser speed), more traffic to the server and most importantly very hard to make interfaces consistent. (There can be many additions and removals of small operations over the time). Check this to learn more about granularity.
  • Business Process Automation (BPA) is impossible: Your partner companies can not purchase your products through their systems. Because they are only given a browser interface, which need human interaction. You should provide some remote interface to allow their computers to talk to your systems.
    bpa-impossibility
    For BPA, interoperability is really important. Because your partner company may run on completely different platform and use completely different languages. I already proved traditional design will not suit to situation where interoperability is need.
  • Lack of security: With the above approach you have to depend on the transport level security, which is handled by your OS. There can be applications (malicious codes) run top of your OS which have back doors to these information. So for business critical messages you need to have message level security (application to application security) which secure the messages by application itself .
  • Lack of reliability: In any case if the connection is lost, will my messages completely lost?. Here too you depend on the transport level reliability which you don’t have much control of.

So now lets turn to our main topic.

SOA Way of Writing PHP

SOA Model

With SOA, you application is no longer presenting the ‘View’ component directly. Instead it provides your business operations as a Web Service. You may implement a View with PHP using this web service. This approach allows you to implement View not only in PHP but also in other languages like .NET, Java or C as web application or desktop applications.

The business logic access the Data Layer through a Data Service. Simmilarly It can use third party Data services, Web Services to extract out the Data needed in the business process.

Let’s see how it helps you to solve the problems arouse in the traditional approach.

  • Less Server load: The SOA components are natively distributed. You don’t need to process the View and the Data in the same server you process the Buisness Logic.
  • High Interoperability: SOA communication happens through Web Services which is a standard protocol. There are implementations for web services in many languages and for many platforms. You can replace any components with any implementation you prefer. For an example you may first write your business logic in PHP, And as the server load goes high, you can write the buisness module in native language (‘C’) and easily intergreate to the system, without being bother of changing other components.
  • Coarse grained Interfaces: The latest web services standards (e.g. WSDL 2.0) enforce the use of documents for messaging rather than invoking remote procedures. This causes the system to be consistent, maintainable and more responsive.
  • Business Process Automation: Web service provide a platform to machine to machine communication. With the availability of interoperability two companies who use different implementations can communicate easily
  • Security: With a WS-Security implementation you can get message level security in your application. For PHP developers there were no implementation or library that can provide  WS-Security sometime ago. But as WSF/PHP is launched with many implementations for WS-* stack, that gap was closed.
  • Reliability: With the WS-Reliable Messaging you can make sure a reliable communication at the application layer. You can use WSF/PHP to do reliable messaging in PHP

As your business get more complicated you can divide the logic too in to several service components as you do with data and view components. This allows you to extend your application very easily. Here is a rough design of an enterprise SOA application that you may have seen in Java and .NET paradigms. And it is time to see more of these in PHP space as well.

SOA design

In RESTful paradigm we give a piece of data ( or in other word ‘Resource’) a unique URL. And in order to manipulate data we use HTTP verbs POST/PUT (create, update), GET (read), DELETE (delete). For an example
take the scenario of manipulating Students data in a high school. Here is how each operation is mapped to a http request (URL + HTTP verb)

HTTP request Operation
POST api/students/ben Create the resource (peice of data) called ben as a student. HTTP body or the url itself (e.g. api/students/ben?age=15&country=xx) may contain the required information about ben
GET api/students/ben Retrieve the information about ben.
PUT api/students/ben Update ben
DELETE api/student/ben Delete the student called ‘ben’.

With the addition of all these HTTP verbs WSO2 WSF/PHP 2.0.0 become a great tool for RESTful developers. Specially with the introducing Data Services library it was so easy to make your database a REST service. I m thinking of preparing a series of application to demonstrate the power of WSF/PHP with all these new features.

This demo -RESTful School- shows how you map a URL to a peice of data. Here we use only the http “GET” method (which is the most to used in practicle data service).

Here is some description of the operations you find in there. Just check the source code for RESTful School demo to see how this is done in code level.

Operation URL SQL Query Note
Get All subjects
subjects
SELECT subjectName, subjectTeacher FROM Subjects
With no parameters
Get subject information From Name
subjects/{name}
SELECT subjectName, subjectTeacher FROM Subjects where SubjectName = ?
The single parameter feed from prepared statement syntax
Get All students
students
SELECT * FROM Students
Again no parameters
Get students From Name
students/{name}
Inner Query:

SELECT subjectName, marks FROM Marks m, Subjects s ".
        " where m.studentId = ? and m.subjectID = s.subjectId

Outer Query

SELECT * FROM Students where StudentName = ?
Nested query, Inner query is called from outer query
Get Marks per Students per Subjects
students/{student}/marks/{subject}
SELECT marks FROM Marks, Subjects, Students where StudentName = ?".
        " and SubjectName = ? and Marks.subjectId = Subjects.subjectId".
        " and Marks.studentID = Students.StudentId;
Two parameters, and ‘?’ in the sql query..

Earlier I wrote a blog about how to make your wordpress blog a web service using the WSF/PHP Data Services library. I will expand that post to demonstrate the use of WS-Security features with WSF/PHP.

This time it is a Tag Search service for my wordpress blog. Check the ‘Tag Search’ Data Services Demo from http://ws.dimuthu.org/. The only difference is here you are authenticated before accessing the service using the username tokens as specified in WS-Security.

Just look at the WSSecurity constructor in the Data Service Demo Code. You can observe 4 new parameters passed in to it. (In addition to the “config” and “operations” options)

  • policy – This is where you specify the policy governed by the service.  Here you can either use the WS-Policy compliant policy file or just a simple PHP array that contain the required security token informations.
    $sec_array = array("useUsernameToken" => TRUE);
    $policy = new WSPolicy(array("security"=>$sec_array));
  • securityToken: You specify the user parameters like how you handle the authentication and the encoding type in this option.
    $security_token = new WSSecurityToken(array("passwordCallback" => "password_callback_function",
                                           "passwordType" => "Digest"));
    
    /* callback function
     * @param string $username username of the client request
     * @return string $password password for that username
     */
    function password_callback_function($username) {
        // In the real word I should authenticate users from database.
        // for this demo I have a simple if-else block
    
        if($username == "visitor") {
            return "visitor123";
        }
    
        return "notavistor";
    }

    Note that here you specify a callback function to the security token parameter. Inside this function you retrieve the password for the user (mostly from the database) and return. WSF/PHP will authenticate the user from these information.

  • useWSA : You need to set this option in order to generate the WS-Addressing parameters (like action) for your WSDL. WS-Addressing is required to run web services with WS-Security in WSF/PHP.
  • actions: You should provide a map of action to service operations in order to get the WS Addressing information generated with your WSDL.
    $actions = array("http://ws.dimuthu.org/blog/getPosts" => "getPosts");

    Just have a look at how these information are rendered in the generated WSDL, http://ws.dimuthu.org/blog/WordpressTagSearchService.php?wsdl. (Note the wsaw:action attribute in the messages inside the portType element.

After you deploy the service, it is very easy to generate a client with the WSDL. If you write clients in PHP you can use the wsdl2php tool shipping with WSF/PHP.  The code for my demo client can be found in http://ws.dimuthu.org/source.php?src=tag.search.client. (There I have hard coded the username and password just for the demo purpose)

September 12th, 2008WSO2 WSF/PHP 2.0.0 Just Released!

We have been waiting for a while to do the WSF/PHP 2.0.0 release with a bundle of new features. We took time to test all the features and to make sure they are working smoothly. And it is heavily tested for the interoperability specially with .NET for WS-Security and WS-Reliable Messaging scenarios. And the newly added Data Services library will be a great tool for the PHP community to bring their LAMP/WAMP applications to the SOA platform. WSF/PHP 2.0.0 is not just a SOAP library. It is ready for the RESTful applications as well with the improved support for HTTP verbs.

Here is the list of new features introduced in this release

  • Added PKCS12 Keystore Support
  • Added Secure Conversation Support
  • Added Replay Detection Support
  • Contract First Web Services support for MTOM
  • SWA ( Soap With Attachments ) Support added
  • MTOM Attachment caching support added
  • HTTP Chunking support added
  • REST API Improved to support HTTP verbs GET,DELETE,PUT and POST
  • New PHP Data Services Solution
  • WS-RM 1.1 added

Have look at the WSF/PHP 2.0.0 Official Release Note for the complete feature list

We use the term DataServices for exposing a Database as a WebService. PHP DataServices library make this task easy by providing a very simple API to the developers.

The API is designed to let the service developer to provide the database configurations, input message format, output message format and the SQL query information. So reading and parsing the input SOAP message, building the response SOAP message from the queried data, serving the WSDL and providing the Database independent layer (with the help of PDO extensions) are done by the Dataserivce library.

Configurations

You give your database configurations in this format.

// database configuraitons
$config = array(
      "db" => "mysql", //your sql
      "username" => DB_USERNAME, //your username
      "password" => DB_PASSWORD, //your password
      "dbname" => "ds", //your database name
      "dbhost" => "localhost"); //your database host

Input Format

You have to declare the names and the types of the content of your input message. This is needed to generate the WSDL and invoke the database query with parameters.

// input format array(param_name => SQL_TYPE)
$inputFormat = array("customerNumber" => "INT");

Output Format

You can customize your response SOAP message by providing the names of the wrapper elements  for both the message and the rows.

// output format, plese check the API from http://wso2.org/wiki/display/wsfphp/API+for+Data+Services+Revised
$outputFormat = array("resultElement" => "Orders", //the name of the wrapper element of the message
                      "rowElement" => "Order", //the name of the wrapper element of each row
                      "elements" => array( "order-number" => "OrderNumber",
                                           "order-date" => "OrderDate",
                                           "status" => "status"));

Create the Query

The query in the PHP dataserivces term is not just the SQL query that you are familiar in accessing a database, It contains the input and output formats in addition to the actual SQL query to invoke.

// sql statment to execute
$sql="select o.OrderNumber, o.OrderDate, o.status from Customers c, Orders o where c.customerNumber=o.customerNumber and c.customerNumber=?";

// operations are consist of inputFormat (optional), outputFormat(required), sql(sql), input_mapping(optional)
$operations = array("customerOrders" =>array("inputFormat" => $inputFormat, "outputFormat" => $outputFormat, "sql" => $sql));

DataService object

Finally you create the DataService object with the provided configurations and the query information.

require_once("wso2/DataServices/DataService.php");

$my_data_service = new DataService(array("config" => $config,"operations" => $operations));

$my_data_service->reply();

If you have a shared hosting environment you will find it is not straight forward to install WSO2 WSF/PHP + PHP DataServices Library since you have very limited authority on your environment. Here in this post, I’m explaining the steps I followed in setting up my custom PHP, WSF/PHP Extension and DataServices library for http://ws.dimuthu.org (This is a shared hosting environment from dreamhost based on LAMP stack) which I’m using to expose my blog as a WebService.

Prerequisites:

  1. You should be able to run PHP using mod_fastcgi (not using mod_php) in Apache. That allows you to configure your own php environment.
  2. The server configurations managed by the hosting service should allow you to handle .php extension from your own  CGI executable (here it is php.cgi), If not, you can still try with setting some other extension (say .phq or .qhq, anything not .php) to be handled by your php-cgi. Anyway if your hosting service allow you to run CGI then most probably you have this permission.
  3. You should have the access to the shell (using SSH) and should be able to use development libraries(libxml, libxsl, libopenssl) + build tools (make)
  4. There can be some other restrictions that your hosting service has put on you, that I have not experienced with my hosting service. So please check your hosting service support and documentation for possibility of building your own PHP environment.

Install PHP:

I have extracted out most of the steps from dreamhost documentation on custom php.ini.

  1. Download PHP and compile. You should at least enable –enable-fastcgi –enable-force-cgi-redirect in the configuration.
    ./configure --enable-fastcgi --enable-force-cgi-redirect --with-xsl --with-openssl --prefix=`pwd`/dist
    make
    make install

    Note: from here on, php source directory is referred as <php_source_directory>
    I have installed the php to <php_source_directory>/dist since we mostly don’t have permission to install it in to default location. (/usr/local). From here on I will be referring php installation directory as <php_install_dir>

  2. create a directory called ‘cgi-bin’ to your web document root directory(<document_root_directory>) and copy the <php_source_directory>/dist/bin/php-cgi in to that. (before php version 5.2.1 there is no php-cgi generated, you can just copy the php to the cgi-bin directory). And rename the php-cgi to php.cgi.
    cp <php_install_direcory>/bin/php-cgi <document_root_directory>/cgi-bin/php.cgi
  3. copy <php_source_direcory/php.ini-dist to the cgi-bin directory and rename it as php.ini, this can be used to configure your php environment.
    cp <php_source_directory/php.ini-dist <document_root_directory>/cgi-bin/php.ini
  4. Create .htaccess file in the cgi-bin directory to allow the access to php-cgi and php.ini files.
    cat << EOF ><document_root_directory>/cgi-bin/.htaccess
    Options +ExecCGI -Indexes +FollowSymLinks
    <FilesMatch "php(.?)\\.(cgi|ini)$">
    Order Deny,Allow
    Deny from All
    Allow from env=REDIRECT_STATUS
    </FilesMatch>
    
    EOF
  5. Create .htaccess file in the root directory redirect all the requests for .php extensions to go through our php-cgi.
    cat << EOF > <document_root_directory>/.htaccess
    AddHandler php-cgi .php
    Action php-cgi /cgi-bin/php.cgi
    EOF

    If your hosting service doesn’t allow to handle .php just rename the end of the first line to some other extension.

  6. Check the necessary permissions levels in files.
    chmod 644 <document_root_directory>/.htaccess
    chmod 755 <document_root_directory>/cgi-bin
    chmod 644 <document_root_directory>/cgi-bin/.htaccess
    chmod 644 <document_root_directory>/cgi-bin/php.ini
    chmod 755 <document_root_directory>/cgi-bin/php.cgi

That’s it. Now your .php files should be run on your own php environment. Just to check whether it is working or not create a phpinfo() file.

cat <<EOF > phpinfo.php
<?php
phpinfo();
?>
EOF

And go to the http://yourdoman.com/phpinfo.php and verify that it is your custom php environment .

Installing WSF/PHP

  1. Download WSF/PHP latest version and extract it to any of your preferred directory(<wsf_php_source_directory>).
  2. Set the PATH environment variable to search for your custom php installation first.
  3. export PATH=<php_install_dir>/bin:$PATH
  4. From the same shell go to the <wsf_php_source_directory> and compile it.
    ./configure
    make
    make install
  5. Now check where you have installed wsf/php. it is in fact the extension dir shown by the php-config command.
    php-config --extension-dir

    I will refer this directory as <php_extension_directory>

  6. Open the <document_root_directory>/cgi-bin/php.ini an set the extension directory, enable wsf extension and set the include path to the wsf scripts directory.cat <<EOF >> <wsf_php_source_directory>/cgi-bin/php.ini
    cat <<EOF >> <wsf_php_source_directory>/cgi-bin/php.ini
    extension_dir=<php_extension_directory>
    extension=wsf.so
    include_path=".:<wsf_php_source_directory>/scripts"
    
    EOF

    If you found that you can only put relative directories in your php.ini (that happens when you don’t even have the read access to your root directory ‘/’), follow the workaround mentioned in here, http://phpwebservices.blogspot.com/2008/08/installing-wsfphp-in-third-party.html

That’s all. Just check the phpinfo (created earlier section) whether your configurations and the wsf extension are loaded correctly. In order to test the functionality copy the wsf/php samples to the web document root and access them from the browser. Go to each sample and verify they function as expected.

cp /samples <wsf_php_source_directory>/ -R

And go to http://yourdomain.com/samples and click on each samples. If this not working most probably your localhost to ip mapping is wrong, most probably this problem is there in your shared host. Just go to the samples directory and change the endpoint to the domain name in place of ‘localhost’ in each client and try it again.

Installing PHP DataServices:

  1. Download and unpack PHP DataServices. <php_data_services_directory>
  2. Update the include_path entry in php.ini to DataServices libraries directory as well. So the <wsf_php_source_directory>/cgi-bin/php.ini  file now has the following entry.
    include_path=".:<wsf_php_source_directory>/scripts:<php_data_services_directory>/lib"

That’ all for the DataService installation. Please read <php_data_services_directory>/README to run the samples. Anyway if you are sure you did followed these simple steps correctly, go on with your DataService  development. Specially if you have wordpress database, you may start straight away with the making wordpress a DataService.

With PHP DataServices it is just a matter of putting a little configuration php file to make your database available as a web service. I only needed few minutes to make a simple web service from my blog after figuring out my wordpress database structure, http://wpbits.wordpress.com/2007/08/08/a-look-inside-the-wordpress-database/. In this guide, I m exposing the title, date and the content of each of my blog for my service, But you can extend this more the way you prefer.

  1. Download and install WSF/PHP 1.3.2 and PHP Data Services Library. If WSF/PHP 2.0 released by the time you are reading this, (it is to be released in this week), you only need to install WSF/PHP, since the DataServices library is packed with WSF/PHP from 2.0.
  2. Drop the following file (Say WordPressService.php) in to any of your web server document directories.
    <?php
    
    // Make sure you put the DataService.php in your include path
    require_once("wso2/DataServices/DataService.php");
    
    // database configuraitons
    // you have to set your database configurations in here..
    // These entries can be copy and past from the wp-config.php in your wordpress installation
    
    $config = array(
    "db" => "mysql",
    "username"=>DB_USER,
    "password"=> DB_PASSWORD,
    "dbname"=>DB_NAME,
    "dbhost"=>DB_HOST);
    // output format, plese check the API from http://wso2.org/wiki/display/wsfphp/API+for+Data+Services+Revised
    $outputFormat = array("resultElement" => "Posts",
    "rowElement" => "post",
    "elements" => array( "title" => "post_title",
    "content" => "post_content",
    "date" => "post_date"));
    
    // sql statment to execute, note that I assume the table prefix is wp_ (so the table name is wp_posts)
    // just check $table_prefix variable in the wp-config.php of your wordpress installation
    $sql="select post_title, post_content, post_date from wp_posts where post_status='published'";
    
    // operations is consist of inputFormat (optional), outputFormat(required), sql(sql), input_mapping(optional)
    $operations = array("getPosts"=>array("outputFormat"=>$outputFormat, "sql"=>$sql));
    $my_data_service = new DataService(array("config"=>$config,"operations"=>$operations));
    
    $my_data_service->reply();
    ?>
  3. It is all. Just access the above file from a web browser, you see your service is hosted. Here is the endpoint for my service. http://ws.dimuthu.org/blog/WordpressService.php. Since I m using WSF/PHP latest svn, I m able to retrieve the wsdl automatically from http://ws.dimuthu.org/blog/WordpressService.php?wsdl. Please wait for WSF/PHP 2.0 release for ?wsdl feature.
  4. To verify whether your service deployed correctly, you may need to write a simple test client. Yea I too wrote one. Since I have the wsdl generated, I just needed to generate the code for the client from the wsdl using wsdl2php tool. There is an online version of the tool in the wsf/php demo site. Here is the generated code for my client, http://labs.wso2.org/wsf/php/wsdl2phptool.php?wsdl_url=http%3A%2F%2Fws.dimuthu.org%2Fblog%2FWordpressService.php%3Fwsdl. I added the following code to the TODO section in handling response,
        if(is_array($response->post)) {
            foreach($response->post as $post) {
    
                echo "<h2>".$post->title . " - ".$post->date."</h2>";
                echo "<p>";
                echo $post->content;
                echo "</p>";
    
                echo "<hr/>";
            }
        }

    Check my Web Service client for the above service here, http://ws.dimuthu.org/blog/WordpressClient.php.

Now I can call for my blog from any web service enabled platform.

We use the term ‘DataService’ when we expose a database as a web service. WSO2 has a separate product for the DataService space which was earlier shipped bundled with WSAS. There you write a configuration xml explaining what data to be exposed in your database and drop it in the WSAS java app server and you get the DataServices deployed without much effort. Couple of months ago we published PHP DataServices library that allow you do deploy Your DataService within a popular LAMP or WAMP stack. With the WSF/PHP 2.0.0 release, you can have the PHP DataService library bundled with the release, hopefully within next couple of weeks.

One of the main problem DataService developers face is how to design an elegant web service API that will provide the requested information from a row database straightaway. Because when we normalize a database, the very closely related data are spread in different tables just keeping the association with foreign keys. So in order to retrieve the useful information database developers have to write multiple queries to the database. Is that same with DataServices?, Do you have to write multiple web service requests to return some useful data?

No. You don’t. You have Nested Queries to save you. With nested queries you can configure your DataServices, so all the relevent information can be extracted and send as a single SOAP message. I will take a demonstration to explain this.

Say you are working for a company that manufacture or sell electrical equipments, say TVs. And your boss is asking you to prepare a whole list of customers who ordered good from them. He want order information (like order date, status of the order) plus the name of the customers in the list.

Here is the table structure that you have.
Orders

ORDERNUMBER ORDERDATE STATUS CUSTOMERID

Customers

CUSTOMERID CUSTOMERNAME

From this you have to find a list of orders with order date, status (available in Orders table) and ordered customer information available in Customers table. As you may seen you have to query both the tables to get the required data.

First you have to decide a service operation that you going to expose as a web service. Operation is uniquely identified by its name. We will give our operation the name “getOrders”. In fact in our PHP Data Service API we treat a Operation same as a query. In general operation/query has following properties associated with it. Note for the complete API please check this Oxygen Tank Page.
Properties of Data Service Operation/Query

inputFormat This is the map of input element or input parameter to the corresponding type. For our operation there is no input. So we are not setting it here.
outputFormat This is a little tricky option. You have to set several configuration under this.

resultElement The name of the wrapper response element. We will give the name “Orders” here.
rowElement The name we give to wrap the each row of the result. If we give this value something like “Order“, then the result xml will be like,

<orders>
  <order>
    order 1 details
  </order>
  <order>
    next order details
  </order>

  <order>
    etc
  </order>
</orders>
elements The name of elements that is going to be in the response XML map to the real names of columns in the actual query result.
For an example if I give this the following value.

array("Order_number" => "ORDERNUMBER",
      "Order_date" => "ORDERDATE",
      "Status" => "STATUS");

The portion of the response will be like this,

<order>
  <Order_number>
    3
  </Order_number>
  <Order_date>
    2008-06-09
  </Order_date>

  <Status>
    Shipped
  </Status>
</order>
queries Array of queries, (The correct term is nested queries). So here you can set the response to be the result of another query. In fact in order to retrieve the customer name for the corresponding order we are going to write a nested query. Just think a operation that take the customerId as a parameter and return the customer data.

getCustomer(customerId)

You have to build this operation/query from the stat as we are just building the ‘getOrders’ query

attributes, texts, elementsOrder Some other configuration options. we are not using it in here, but by the name you can have an idea what they are for.
sql The standard sql query corresponding to the operation. In our case it is

SELECT o.ORDERNUMBER,o.ORDERDATE, o.STATUS,o.CUSTOMERNUMBER FROM ds.Orders o
inputMapping Finally this describe how the names of the input elements are mapped to the names of input parameters. Since ‘getOrders’ operation doesn’t have input parameters, this is not going to be used in this particular situation.

So as I described in the queries section you have to write the whole thing for the getCustomer operation as well.

$getCustomer = array(
    "inputFormat" => array("customerNumber" => "INTEGER"),
    "outputFormat" => array(

            "resultElement" => "Customers",
            "rowElement" => "Customer",
            "elements" => array("name" => "CUSTOMERNAME")
            ),
    "sql" => "select c.CUSTOMERNAME from ds.Customers c where c.CUSTOMERNUMBER = ?",
    "inputMapping" => array("CUSTOMERNUMBER" => "customerNumber")

    );

And here is the getOrders operation/query that actually use the getCustomer as a part of it.

$getOrders = array(
    "outputFormat" => array(
        "resultElement" => "Orders",
        "rowElement" => "Order",
        "elements" =>  array(

            "Order_number" => "ORDERNUMBER",
            "Order_date" => "ORDERDATE",
            "Status" => "STATUS"),
         "queries" =>  array($getCustomer)
         ),
    "sql" => "select c.CUSTOMERNAME from ds.Customers c where c.CUSTOMERNUMBER = ?"
    );

Then we will to define the operations array which we are going feed to the DataService class. Note that now we have two operations getOrders and getCustomer. From that I used getCustomer to help the building of getOrders. And I don’t want to publish getCustomer as a separate operation. Simply the boss doesn’t ask for that operation :) . So my operation map is like this,

$operations = array("getOrders" => $getOrders);

This operation map will be given as a constructor argument of DataService class. If you are familiar with WSF/PHP WSService class, there is no much different between these two classes. You can give all the options available in the WSService class to the DataService class. Say you want to encrypt the messages, just use the “policy” and the “securityToken” options. So with DataService class you have the luxury of using WS-Security as well as WS-Reliable Messaging for free.

To finish this post I will put the complete code for the above scenario. You can check the same service option in action in the WSF/PHP Demo site (Try the demo4).

<?php
// include the DataService library.
// NOTE: this path is valid only from wsf/php 2.0.0
require_once("wso2/DataServices/DataService.php");

// set the configurations
$config = array("db" => "mysql",
   "username" => "dimuthu",
   "password" => "thiswillnotbeasecretanymore",
   "dbname" => "ds",
   "dbhost" => "localhost");

// getCustomer Query - this used by the getOrders query/operation
$getCustomer = array(
    "inputFormat" => array("customerNumber" => "INTEGER"),
    "outputFormat" => array(

            "resultElement" => "Customers",
            "rowElement" => "Customer",
            "elements" => array("name" => "CUSTOMERNAME")
            ),
    "sql" => "select c.CUSTOMERNAME from ds.Customers c where c.CUSTOMERNUMBER = ?",
    "inputMapping" => array("CUSTOMERNUMBER" => "customerNumber")

    );

// The operation/query getOrders - Read the complete blog to see what 
// each of these option stand for
$getOrders = array(
    "outputFormat" => array(
        "resultElement" => "Orders",
        "rowElement" => "Order",
        "elements" =>  array(

            "Order_number" => "ORDERNUMBER",
            "Order_date" => "ORDERDATE",
            "Status" => "STATUS"),
         "queries" =>  array($getCustomer)
         ),
    "sql" => "select c.CUSTOMERNAME from ds.Customers c where c.CUSTOMERNUMBER = ?"
    );

// operation array
$operations = array("getOrders" => $getOrders);

// create the DataService object and reply
$ds = new DataService(array("operations" => $operations,
          "config" => $config,
          "serviceName" => NextedQuerySample));

$ds->reply();

?>

© 2007 Dimuthu’s Blog | iKon Wordpress Theme by Windows Vista Administration | Powered by Wordpress