Implement SOAP services with the Zend Framework
Implement SOAP services with the Zend Framework
Quickly add SOAP services to your PHP Web application with the Zend Framework
Summary: The Zend Framework is an MVC-compliant framework for building robust, scalable PHP Web applications. It includes a Zend_Soap component that allows developers to quickly and efficiently add SOAP-based Web services to their applications. This article examines the Zend_Soap component in detail, illustrating how you can build a SOAP Web service and examining features such as input validation, fault generation, and WSDL auto-creation.
Tags for this article:api,application_development,http,mysql,php,php_(hypertext_preprocessor),rest,soap,tools,vikram_vaswani...more tags
Date: 11 May 2010
Level: Intermediate
PDF:A4 and Letter(342KB | 24 pages)Get Adobe® Reader®
Also available in: ChineseKoreanJapanese
Activity: 17430 views
Comments:5 (View | Add comment - Sign in)
Web services are all the rage these days, with REST-based services in particular getting the lion's share of the attention. REST is popular because of its simple, intuitive nature and ability to work with existing HTTP methods. But it's worth remembering that REST isn't the only game in town: SOAP, the Simple Object Access Protocol, also provides a more formal, standardized approach to the problem of exchanging information over the Web.
Although SOAP-based services are typically perceived as complex and time-consuming to implement, a number of existing tools can significantly simplify the process. One such tool is the Zend Framework, which offers a complete MVC framework to build scalable Web applications with PHP. In addition to a bunch of other goodies—OOP forms, i18n support, query and page caching, and Dojo integration, just to name a few—the Zend Framework also offers a comprehensive toolkit for creating and deploying SOAP services through its Zend_Soap component.
In this article, you will walk through the process of building a simple SOAP-based Web service with the Zend Framework. In addition to learning to handle client requests and send back SOAP-compliant responses, you also explore the process of handling exceptions and generating SOAP faults. Finally, you also use Zend_Soap to automatically generate a WSDL file that describes the SOAP service, thereby enabling clients to "auto-discover" the SOAP service API.
First up, a few quick words about SOAP. SOAP is a way of exchanging information over the Web using language-independent XML, thereby allowing applications written in different languages to interconnect with each other. This XML is transmitted between client and server using HTTP as the transport protocol, with strong data typing used to guarantee data integrity.
Unlike REST, which revolves aroundresourcesandactions, SOAP is based onmethodsanddata types. While a REST service is typically limited to four operations, corresponding to the four HTTP methods of GET, POST, PUT, and DELETE, a SOAP service has no such limitations; it can expose as many, or as few, methods as the developer cares to define. Further, these methods are typically invoked using the POST HTTP method, with this method bearing no relation to the type of operation being requested.
To illustrate how SOAP works, consider a simple example. Suppose you have a social bookmarking application, and you want to allow third-party developers to add and retrieve bookmarks from the application using SOAP. Typically, you would implement a set of service objects with methods likegetBookmark()
andaddBookmark()
, and expose these service objects through a SOAP server. The server would be responsible for translating SOAP data types to native data types, parsing the SOAP request packet, executing the corresponding server method, and generating a SOAP response packet with the result.
Listing 1has an example of what a SOAP request for the proceduregetBookmark()
might look like:
Listing 1. An example SOAP request
AndListing 2illustrates a sample response:
Listing 2. An example SOAP response
In a typical SOAP transaction, the server accepts an XML-encoded request like the one inListing 1, parses the XML, executes the corresponding service object method, and returns an XML-encoded response like the one inListing 2to the requesting client. The client is usually able to parse and translate this SOAP response into a language-specific object or data structure for further processing. You can use an optional WSDL file to give clients information on the available methods, as well as the number and data types of input arguments and return values.
The Zend Framework comes with implementations for both SOAP clients and servers, as well as for automatic WSDL file generation. The server and client implementations are wrappers around the SOAP extension in PHP; this means that they will not work if the PHP build does not include support for the SOAP extension. That said, using the Zend Framework libraries over the native extension does make things a little simpler, because the developer only needs to define a set of objects that implement the service API and attach them to the server to handle incoming requests. The following sections will discuss this in detail.
Setting up the example application
Before you start to implement a SOAP service, a few notes and assumptions are in order. Throughout this article, I'll assume that you have a working development environment with Apache, PHP+SOAP, and MySQL, that the Zend Framework is installed to your PHP include path, and that you're familiar with the basics of SQL, XML, and SOAP. I'll also assume that you're conversant with the basic principles of application development with the Zend Framework, understand the interaction between actions and controllers, and are familiar with the Zend_Db database abstraction layer. Finally, I'll assume that your Apache Web server is configured to support virtual hosting and URL rewriting through .htaccess files. In case you're not familiar with these topics, you'll find links to more information in theResourcesof this article.
The example SOAP service that you will implement in this article allows third-party developers to add, edit, delete, and retrieve product listings from the application database. It will expose the following methods, all of which you can access using a standard SOAP client:
getProducts()
: Returns all products from the databasegetProduct($id)
: Returns a specific product from the databaseaddProduct($data)
: Adds a new product to the databasedeleteProduct($id)
: Deletes a specific product from the databaseupdateProduct($id, $data)
: Updates a specific product in the database with new values
Step 1: Initialize a new application
To begin, first set up a standard Zend Framework application that provides the context for the code shown in this article. Use the Zend Framework tool script (zf.bat on Windows® or zf.sh on UNIX)™ to initialize a new project, as shown below:
You can now define a new virtual host for this application, such as http://example.localhost/, in your Apache configuration, and point the virtual host's document root to the application's public/ directory. If you then browse to this host, you should see the default Zend Framework welcome page, as inFigure 1.
Figure 1. The default Zend Framework welcome page
![Screen capture of the default Zend Framework welcome page](http://www.ibm.com/developerworks/webservices/library/x-zsoap/image1.jpg)
Step 2: Initialize the application database and model
The next step is to initialize the application database. So, create a new MySQL table to hold product information, as below:
Populate this table with some sample records to get things started, as below:
Step 3: Configure the application namespace
The final step is to configure the application namespace for the Zend Framework autoloader. This step helps to automatically load application-specific classes into the application as needed. In this case, I assume the application namespace isExample
and application-specific classes (such as SOAP service classes) will be stored in $PROJECT/library/Example/. So, update the application configuration file at $PROJECT/application/configs/application.ini and add the following line to it:
You're now all set to start creating a SOAP service!
Since this is an example application, I'll keep things simple and create an action to handle SOAP requests within the default module's IndexController itself; however, in the real world, you'll probably want to maintain a separate controller to handle SOAP requests. Edit the file $PROJECT/application/controllers/IndexController.php and add a new action to it, as inListing 3:
Listing 3. The soapAction() definition
Listing 3initializes a new Zend_Soap_Server object in non-WSDL mode, passing a null value as the first argument to the object constructor. When setting up the server in non-WSDL mode, it is mandatory to specify the server URI; inListing 3, this is specified in the options array passed to the constructor as the second argument.
Next, the server object'ssetClass()
method is used to attach a service class to the server. This class implements the available methods for the SOAP service; the server will automatically call these methods in response to SOAP requests. If you prefer, you can also attach user-defined functions to the server with theaddFunction()
andloadFunctions()
methods, instead of attaching a class with thesetClass()
method.
As noted previously, the Zend_Soap_Server class doesn't provide a SOAP server implementation of its own; it merely provides a wrapper around PHP's built-in SOAP extension. And so, once all the preliminaries are out of the way, thehandle()
method inListing 3takes care of initializing the built-in PHP SoapServer object, passing it the request object, and invoking that object'shandle()
method to handle the SOAP request.
All this is fine and dandy, but it won't get you very far since the service class hasn't been defined. Create that next, using the code inListing 4and saving the resulting class definition to $PROJECT/library/Example/Manager.php:
Listing 4. The service object with get*() methods defined
Listing 4sets up a standalone service class containing two methods. ThegetProducts()
method uses Zend_Db to retrieve all available product records from the table and return it as an array, while thegetProduct()
method accepts a product identifier and returns only the specified record. The SOAP server will then convert the method return value into a SOAP response packet and send it back to the requesting client.Listing 8has an example of what this response packet looks like:
In case you wonder where Zend_Db is initialized, this is done in the application bootstrapper, at $PROJECT/application/Bootstrap.php. The Bootstrap.php file contains an_initDatabase()
function that sets up the Zend_Db adapter and registers it with the application registry.Listing 5has the code:
Listing 5. Database adapter initialization
To see this in action, create a SOAP client (Listing 6) and use it to connect to the SOAP service and request thegetProducts()
method.
Listing 6. An example SOAP client
The SOAP client will generate a request packet (Listing 7).
Listing 7. A sample SOAP request for the getProducts() method
The server will respond to this with a SOAP-encoded response (Listing 8).
Listing 8. A sample SOAP response for the getProducts() method
The SOAP client will then convert this response back into a native PHP array that can be processed or inspected further, as inFigure 2.
Figure 2. The result of the SOAP request, converted to a native PHP array
![The result of the SOAP request, converted to a native PHP array](http://www.ibm.com/developerworks/webservices/library/x-zsoap/image2.jpg)
Adding, deleting and updating data
So that takes care of retrieving data over SOAP. Now, how about adding and deleting data?
It's quite easy to implement anaddProduct()
method in the Example_Manager class.Listing 9demonstrates what this looks like:
Listing 9. The SOAP service object, with the addProduct() method defined
TheaddProduct()
method inListing 9accepts a new product record as an array of key-value pairs and then uses the Zend_Db object'sinsert()
method to write this record to the database table. It returns the ID of the newly inserted record.
Deleting products is equally simple: just add adeleteProduct()
method which accepts the product ID as input, and then uses the Zend_Dbdelete()
method to remove the record from the database.Listing 10illustrates what this method looks like:
Listing 10. The SOAP service object, with the deleteProduct() method defined
InListing 10, the second argument passed to thedelete()
method specifies the constraint or filter to be used when performing the DELETE operation. Including this argument is key; without it, Zend_Db will delete all records in the table.
Finally,Listing 11illustrates anupdateProduct()
method, which can be used to update a product record with new values. This method accepts two input arguments—the product ID and an array containing the revised record—and uses Zend_Db'supdate()
method to execute an UPDATE query on the database table.
Listing 11. The SOAP service object with the updateProduct() method defined
You can try all of these out with a SOAP client like the one inListing 12:
Listing 12. An example SOAP client
One problem with all the methods shown in previous sections: they don't include any input validation or filters. In the real world, omitting this type of validation has serious implications for the integrity of your application database, and can quickly result in data corruption (at best) or outright vandalism (at worst).
Fortunately, the Zend Framework includes a Zend_Validate component, which provides built-in validators for the most common scenarios. You can couple this feature with the Zend_Soap_Server'sregisterFaultException()
method to test the request data provided by the client, and send back a SOAP fault under various error scenarios.
To see how this works, begin by creating a custom exception class that extends Zend_Exception, as inListing 13:
Listing 13. A custom Exception class
Save this class to $PROJECT/library/Example/Exception.php.
Next, update the various service class methods to include input validation, and to throw the custom exception if the input data is invalid or missing.Listing 14illustrates the revised Example_Manager class:
Listing 14. The revised SOAP service object, with input validation and exceptions
InListing 14, the service API was strengthened to include validation for all input parameters. For most of the API methods, theZend_Validate::is()
static method provides a convenient way to test the input arguments; in some cases, an additional Zend_Filter_Input filter chain is used to both validate and filter the input. Any errors arising through the input validation process are raised as instances of the Example_Exception class.
The final step is to tell the SOAP server to automatically convert raised Example_Exceptions into SOAP faults. This is done by registering the exception class with the SOAP server using theregisterFaultException()
method, as in the revisedIndexController::soapAction
inListing 15:
Listing 15. The revised soapAction() definition, with support for raising custom exceptions as faults
To see this in action, try sending a SOAP request for thegetProduct()
method and pass it an invalid ID.Listing 16has an example of one such SOAP request:
Listing 16. A SOAP request with invalid input arguments
The server will validate the input and, finding it to be invalid, will raise an Example_Exception, which will be converted to a SOAP fault and sent back to the client.Listing 17illustrates what the response packet will look like:
Listing 17. A generated SOAP fault
From the SOAP client perspective, it's a good idea to wrap the SOAP call inside a try-catch block, so that SOAP faults like the one above can be caught and handled gracefully. If you revisit the example SOAP client inListing 12, you'll see an example of how this can be done.
One drawback of the native SOAP extension in PHP is that it doesn't include support for automatically generating WSDL files for a SOAP service. WSDL files are useful, because they contain information on available SOAP API methods and can be used by connecting clients to "auto-discover" the SOAP API.
The Zend Framework, however, includes a Zend_Soap_AutoDiscover component that you can use to automatically generate a WSDL file for a SOAP service. It does this by reading PHPDoc comments within the SOAP service class, and converting these comments into a WSDL document. If you look through the previous listings in this article, you'll see that each method is accompanied with PHPDoc comments; this is deliberately done to make WSDL auto-generation simpler.
Listing 18illustrates how to set up WSDL auto-generation with the Zend_Soap_AutoDiscover component:
Listing 18. The wsdlAction() definition
Listing 18defines a newwsdlAction()
, which initializes an instance of the Zend_Soap_AutoDiscover component and points it to the Example_Manager class. Invoking this instance'shandle()
method results in it reading the specified class, parsing the PHPDoc comments within it, and generating a standards-compliant WSDL document that fully describes the service object.
To see the result, point your browser to http://example.localhost/index/wsdl, and you should see something likeFigure 3:
Figure 3. A dynamically generated WSDL file
![Screen capture of a dynamically generated WSDL file](http://www.ibm.com/developerworks/webservices/library/x-zsoap/image3.jpg)
It now becomes possible for both SOAP server and client to use this WSDL file, instead of manually specifying theuri
andlocation
parameters.Listing 18demonstrates this as well, by revising thesoapAction()
such that it passes the WSDL URL to the Zend_Soap_Server constructor to have it start up in WSDL mode. Connecting SOAP clients can also use this WSDL URL to auto-discover the SOAP service API.
The Zend Framework provides a complete toolkit for quickly and efficiently adding a SOAP API to a Web application. With this toolkit, you can enable information exchange between Web applications in an economical and efficient manner, using the well-understood SOAP standard. The Zend Framework's built-in support for SOAP clients and servers, and for WSDL auto-generation, makes it a good choice for rapid SOAP service implementation and deployment. And finally, because the Zend Framework is an MVC-compliant framework, it is also quite easy to graft a SOAP API on to an existing Zend Framework application with minimal impact on the existing codebase (and correspondingly fewer regressions to worry about).
For links to all the code implemented in this article, together with a simple SOAP client that you can use to try adding, editing, deleting and retrieving products, seeDownloads. For the tools used in this artilce, seeResources. I'd recommend you get the code, start playing with it, and maybe try your hand at adding new things to it. I guarantee you won't break anything, and it will definitely add to your learning. Have fun!
Information about download methods
Learn
- TheW3C SOAP specification: Improve your understanding of SOAP, a lightweight, XML-based protocol for exchange of information.
- Theofficial Zend Framework Web site: Learn more about this open source, object-oriented Web application framework for PHP 5 on .
- TheZend Framework Quickstart: Jump into application development with the Zend Framework.
- TheZend Framework manual: Take a closer look at the Zend_Soap component.
- The Zend Framework API docs: Review API documentation for each minor release, or view the latest online.
- TheZend Framework Community mailing listsandZend Contributors wiki: Participate in the Zend Framework community, ask questions and get answers on .
- More articles by this author(Vikram Vaswani, developerWorks, August 2007-current): Read articles about XML, additional Google APIs and other technologies.
- My developerWorks: Personalize your developerWorks experience.
- IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.
- XML technical library: See the developerWorks XML Zone for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.
- developerWorks technical events and webcasts: Stay current with technology in these sessions.
- developerWorks on Twitter: Join today to follow developerWorks tweets.
- developerWorks podcasts: Listen to interesting interviews and discussions for software developers.
Get products and technologies
- The Zend Framework: Download the latest Zend Framework releases.
- The MySQL database server: Download the open source transactional database used in this article.
- DB2 Express-C: Get a free version of the IBM DB2 database server, an excellent foundation for application development for small and medium business.
- IBM product evaluation versions: Download orexplore the online trials in the IBM SOA Sandboxand get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
- XML zone discussion forums: Participate in any of several XML-related discussions.
- developerWorks blogs: Check out these blogs and get involved.
![Photo of Vikram Vaswani](http://www.ibm.com/developerworks/i/p-vvaswani.jpg)
Vikram Vaswani is the founder and CEO ofMelonfire, a consulting services firm with special expertise in open-source tools and technologies. He is also the author of the booksMySQL Database Usage and Administration,PHP: A Beginners Guideand the upcomingZend Framework: A Beginners Guide.
Average rating (7 votes)
Brilliant article.
Can you explain what is required to make this soap web service available over https? And what would the corresponding client code look like (using Zend Soap Client)?
Posted byredlawsteron 15 December 2010
Thank you for putting together such a work-through example. The only problem I came across was about the virtual host set-up during testing (e.g. http://localhost/dev/test_soapClient.php), but after I added "localhost" as virtual host, everything works. Great!
Posted byVivianon 04 October 2010
Hello,
Thanks for this nice article about web service.
Here i have try this example but i am not able to create wsdl file using soap action in this action you have used Zend_Soap_Server class object.
When i try to create wsdl file using soapAction then following error occured.
−
WSDL
−
SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost/example-app-soap/index/wsdl'
Please give me solution for this problem.
Thanks and Regards.
Jignesh Chauhan
Posted byJigneshmcaon 19 August 2010
Thanks for your kind comments.
I corrected the broken download URL and republished the article so the download works now. The correct download URL is: http://public.dhe.ibm.com/software/dw/xml/x-zsoap/example-app-soap.zip
Posted byv_dulcimeron 14 May 2010
Very nice article. That was what I am looking for to test my web services. Unfortunately I couldn't download the code as it shows an invalid page.
Posted bythbehon 13 May 2010
POST /soap HTTP/1.1 Host: localhost Connection: Keep-Alive User-Agent: PHP-SOAP/5.3.1 Content-Type: application/soap+xml; charset=utf-8 Content-Length: 471 <?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://example.localhost/index/soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="http://www.w3.org/2003/05/soap-encoding"> <env:Body> <ns1:getBookmark env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"> <param0 xsi:type="xsd:int">4682</param0> </ns1:getBookmark> </env:Body> </env:Envelope> |
HTTP/1.1 200 OK Date: Wed, 17 Mar 2010 17:13:28 GMT Server: Apache/2.2.14 (Win32) PHP/5.3.1 X-Powered-By: PHP/5.3.1 Content-Length: 800 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: application/soap+xml; charset=utf-8 <?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://example.localhost/index/soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:enc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <env:Body xmlns:rpc="http://www.w3.org/2003/05/soap-rpc"> <ns1:getBookmarkResponse env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"> <rpc:result>return</rpc:result> <return enc:itemType="xsd:string" enc:arraySize="3" xsi:type="enc:Array"> <item xsi:type="xsd:string">http://www.google.com</item> <item xsi:type="xsd:string">http://www.php-programming-solutions.com </item> <item xsi:type="xsd:string">http://www.mysql-tcr.com</item> </return> </ns1:getBookmarkResponse> </env:Body> </env:Envelope> |
shell> zf.bat create project example |
mysql> CREATE TABLE IF NOT EXISTS products ( -> id int(11) NOT NULL AUTO_INCREMENT, -> title varchar(200) NOT NULL, -> shortdesc text NOT NULL, -> price float NOT NULL, -> quantity int(11) NOT NULL, -> PRIMARY KEY (id) -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
mysql> INSERT INTO products (id, title, shortdesc, price, quantity) VALUES(1, -> 'Ride Along Fire Engine', 'This red fire engine is ideal for toddlers who want -> to travel independently. Comes with flashing lights and beeping horn.', -> 69.99, 11); Query OK, 1 row affected (0.08 sec) mysql> INSERT INTO products (id, title, shortdesc, price, quantity) VALUES(2, -> 'Wind-Up Crocodile Bath Toy', 'This wind-up toy is the perfect companion for hours -> of bathtub fun.', 7.99, 67); Query OK, 1 row affected (0.08 sec) |
autoloaderNamespaces[] = "Example_" |
<?php class IndexController extends Zend_Controller_Action { public function soapAction() { // disable layouts and renderers $this->getHelper('viewRenderer')->setNoRender(true); // initialize server and set URI $server = new Zend_Soap_Server(null, array('uri' => 'http://example.localhost/index/soap')); // set SOAP service class $server->setClass('Example_Manager'); // handle request $server->handle(); } } |
<?php class Example_Manager { /** * Returns list of all products in database * * @return array */ public function getProducts() { $db = Zend_Registry::get('Zend_Db'); $sql = "SELECT * FROM products"; return $db->fetchAll($sql); } /** * Returns specified product in database * * @param integer $id * @return array|Exception */ public function getProduct($id) { if (!Zend_Validate::is($id, 'Int')) { throw new Example_Exception('Invalid input'); } $db = Zend_Registry::get('Zend_Db'); $sql = "SELECT * FROM products WHERE id = '$id'"; $result = $db->fetchAll($sql); if (count($result) != 1) { throw new Exception('Invalid product ID: ' . $id); } return $result; } } ?> |
<?php class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initDatabase() { $db = new Zend_Db_Adapter_Pdo_Mysql(array( 'host' => 'localhost', 'username' => 'user', 'password' => 'pass', 'dbname' => 'example' )); Zend_Registry::set('Zend_Db', $db); } } |
<?php // load Zend libraries require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Soap_Client'); // initialize SOAP client $options = array( 'location' => 'http://example.localhost/index/soap', 'uri' => 'http://example.localhost/index/soap' ); try { $client = new Zend_Soap_Client(null, $options); $result = $client->getProducts(); print_r($result); } catch (SoapFault $s) { die('ERROR: [' . $s->faultcode . '] ' . $s->faultstring); } catch (Exception $e) { die('ERROR: ' . $e->getMessage()); } ?> |
<?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://example.localhost/index/soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:enc="http://www.w3.org/2003/05/soap-encoding"> <env:Body> <ns1:getProducts env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"/> </env:Body> </env:Envelope> |
<?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://example.localhost/index/soap" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:enc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <env:Body xmlns:rpc="http://www.w3.org/2003/05/soap-rpc"> <ns1:getProductsResponse env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"> <rpc:result>return</rpc:result> <return enc:itemType="ns2:Map" enc:arraySize="2" xsi:type="enc:Array"> <item xsi:type="ns2:Map"> <item> <key xsi:type="xsd:string">id</key> <value xsi:type="xsd:string">1</value> </item> <item> <key xsi:type="xsd:string">title</key> <value xsi:type="xsd:string">Ride Along Fire Engine</value> </item> <item> <key xsi:type="xsd:string">shortdesc</key> <value xsi:type="xsd:string">This red fire engine is ideal for toddlers who want to travel independently. Comes with flashing lights and beeping horn.</value> </item> <item> <key xsi:type="xsd:string">price</key> <value xsi:type="xsd:string">69.99</value> </item> <item> <key xsi:type="xsd:string">quantity</key> <value xsi:type="xsd:string">11</value> </item> </item> ... </return> </ns1:getProductsResponse> </env:Body> </env:Envelope> |
<?php class Example_Manager { /** * Adds new product to database * * @param array $data array of data values with keys -> table fields * @return integer id of inserted product */ public function addProduct($data) { $db = Zend_Registry::get('Zend_Db'); $db->insert('products', $data); return $db->lastInsertId(); } } |
<?php class Example_Manager { /** * Deletes product from database * * @param integer $id * @return integer number of products deleted */ public function deleteProduct($id) { $db = Zend_Registry::get('Zend_Db'); $count = $db->delete('products', 'id=' . $db->quote($id)); return $count; } } |
<?php class Example_Manager { /** * Updates product in database * * @param integer $id * @param array $data * @return integer number of products updated */ public function updateProduct($id, $data) { $db = Zend_Registry::get('Zend_Db'); $count = $db->update('products', $data, 'id=' . $db->quote($id)); return $count; } } |
<?php // load Zend libraries require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Soap_Client'); // initialize SOAP client $options = array( 'location' => 'http://example.localhost/index/soap', 'uri' => 'http://example.localhost/index/soap' ); try { // add a new product // get and display product ID $p = array( 'title' => 'Spinning Top', 'shortdesc' => 'Hours of fun await with this colorful spinning top. Includes flashing colored lights.', 'price' => '3.99', 'quantity' => 57 ); $client = new Zend_Soap_Client(null, $options); $id = $client->addProduct($p); echo 'Added product with ID: ' . $result; // update existing product $p = array( 'title' => 'Box-With-Me Croc', 'shortdesc' => 'Have fun boxing with this inflatable crocodile, made of tough, washable rubber.', 'price' => '12.99', 'quantity' => 25 ); $client->updateProduct($id, $p); echo 'Updated product with ID: ' . $id; // delete existing product $client->deleteProduct($id); echo 'Deleted product with ID: ' . $id; } catch (SoapFault $s) { die('ERROR: [' . $s->faultcode . '] ' . $s->faultstring); } catch (Exception $e) { die('ERROR: ' . $e->getMessage()); } ?> |
<?php class Example_Exception extends Zend_Exception {} |
<?php class Example_Manager { // define filters and validators for input private $_filters = array( 'title' => array('HtmlEntities', 'StripTags', 'StringTrim'), 'shortdesc' => array('HtmlEntities', 'StripTags', 'StringTrim'), 'price' => array('HtmlEntities', 'StripTags', 'StringTrim'), 'quantity' => array('HtmlEntities', 'StripTags', 'StringTrim') ); private $_validators = array( 'title' => array(), 'shortdesc' => array(), 'price' => array('Float'), 'quantity' => array('Int') ); /** * Returns list of all products in database * * @return array */ public function getProducts() { $db = Zend_Registry::get('Zend_Db'); $sql = "SELECT * FROM products"; return $db->fetchAll($sql); } /** * Returns specified product in database * * @param integer $id * @return array|Example_Exception */ public function getProduct($id) { if (!Zend_Validate::is($id, 'Int')) { throw new Example_Exception('Invalid input'); } $db = Zend_Registry::get('Zend_Db'); $sql = "SELECT * FROM products WHERE id = '$id'"; $result = $db->fetchAll($sql); if (count($result) != 1) { throw new Example_Exception('Invalid product ID: ' . $id); } return $result; } /** * Adds new product to database * * @param array $data array of data values with keys -> table fields * @return integer id of inserted product */ public function addProduct($data) { $input = new Zend_Filter_Input($this->_filters, $this->_validators, $data); if (!$input->isValid()) { throw new Example_Exception('Invalid input'); } $values = $input->getEscaped(); $db = Zend_Registry::get('Zend_Db'); $db->insert('products', $values); return $db->lastInsertId(); } /** * Deletes product from database * * @param integer $id * @return integer number of products deleted */ public function deleteProduct($id) { if (!Zend_Validate::is($id, 'Int')) { throw new Example_Exception('Invalid input'); } $db = Zend_Registry::get('Zend_Db'); $count = $db->delete('products', 'id=' . $db->quote($id)); return $count; } /** * Updates product in database * * @param integer $id * @param array $data * @return integer number of products updated */ public function updateProduct($id, $data) { $input = new Zend_Filter_Input($this->_filters, $this->_validators, $data); if (!Zend_Validate::is($id, 'Int') || !$input->isValid()) { throw new Example_Exception('Invalid input'); } $values = $input->getEscaped(); $db = Zend_Registry::get('Zend_Db'); $count = $db->update('products', $values, 'id=' . $db->quote($id)); return $count; } } |
<?php class IndexController extends Zend_Controller_Action { public function soapAction() { // disable layouts and renderers $this->getHelper('viewRenderer')->setNoRender(true); // initialize server and set URI $server = new Zend_Soap_Server(null, array('uri' => 'http://example.localhost/index/soap')); // set SOAP service class $server->setClass('Example_Manager'); // register exceptions that generate SOAP faults $server->registerFaultException(array('Example_Exception')); // handle request $server->handle(); } } |
<?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://example.localhost/index/soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="http://www.w3.org/2003/05/soap-encoding"> <env:Body> <ns1:getProduct env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"> <param0 xsi:type="xsd:string">nosuchproduct</param0> </ns1:getProduct> </env:Body> </env:Envelope> |
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/> <SOAP-ENV:Body> <SOAP-ENV:Fault> <faultcode>Receiver</faultcode> <faultstring>Invalid input</faultstring> </SOAP-ENV:Fault> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
<?php class IndexController extends Zend_Controller_Action { public function soapAction() { // disable layouts and renderers $this->getHelper('viewRenderer')->setNoRender(true); // initialize server and set WSDL file location $server = new Zend_Soap_Server('http://example.localhost/index/wsdl'); // set SOAP service class $server->setClass('Example_Manager'); // register exceptions that generate SOAP faults $server->registerFaultException(array('Example_Exception')); // handle request $server->handle(); } public function wsdlAction() { // disable layouts and renderers $this->getHelper('viewRenderer')->setNoRender(true); // set up WSDL auto-discovery $wsdl = new Zend_Soap_AutoDiscover(); // attach SOAP service class $wsdl->setClass('Example_Manager'); // set SOAP action URI $wsdl->setUri('http://example.localhost/index/soap'); // handle request $wsdl->handle(); } } |
Description | Name | Size | Download method |
---|---|---|---|
The example application discussed in this article | example-app-soap.zip | 8KB | HTTP |
详见:http://www.ibm.com/developerworks/webservices/library/x-zsoap/index.html?ca=drs-#icomments
Sign inorregisterto leave a comment.
Note: HTML elements are not supported within comments.