• 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

    Vikram Vaswani, Founder, Melonfire

    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.

    Date:  11 May 2010
    Level:  IntermediatePDF:A4 and Letter(342KB | 24 pages)Get Adobe® Reader®
    Also available in: ChineseKoreanJapanese

    Activity:  17430 views
    Comments:5 (View | Add comment - Sign in)

    Average rating 4 stars based on 7 votesAverage rating (7 votes)
    Rate this article

    Introduction

    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.

    Frequently used acronyms

    • API: Application Programming Interface
    • HTTP: Hypertext Transfer Protocol
    • i18n: Internationalization
    • MVC: Model-View-Controller
    • OOP: Object-oriented programming
    • REST: Representational State Transfer
    • SQL: Structured Query Language
    • URI: Uniform Resource Identifier
    • URL: Uniform Resource Locator
    • W3C: World Wide Web Consortium
    • WSDL: Web Services Description Language
    • XML: Extensible Markup Language

    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.

    Understanding SOAP

    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 database
    • getProduct($id): Returns a specific product from the database
    • addProduct($data): Adds a new product to the database
    • deleteProduct($id): Deletes a specific product from the database
    • updateProduct($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

    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 isExampleand 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!

    Retrieving data

    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

    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

    Generating SOAP faults

    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::soapActioninListing 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.

    Adding WSDL support

    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

    It now becomes possible for both SOAP server and client to use this WSDL file, instead of manually specifying theuriandlocationparameters.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.

    Conclusion

    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!


    Download

    Information about download methods


    Resources

    Learn

    Get products and technologies

    Discuss

    About the author

    Photo of Vikram Vaswani

    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.

    Rate this article

    Average rating 4 stars based on 7 votes Average rating (7 votes)

    1 star
    2 stars
    3 stars
    4 stars
    5 stars

    Comments

    Sign inorregisterto leave a comment.

    Note: HTML elements are not supported within comments.

     

    1000 characters left




    Total comments (5)

    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

    Trademarks | My developerWorks terms and conditions

          
    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();
        }
    }
    
    DescriptionNameSizeDownload 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

  • 相关阅读:
    每天一个设计模式(2):观察者模式
    每天一个设计模式(1):策略模式
    每天一个设计模式(0):设计模式概述
    常量池、栈、堆的比较
    常量池小结
    Java虚拟机体系结构分析
    Java并发(3):volatile及Java内存模型
    第一题:Big Countries
    22 高级SQL特性
    21 使用游标
  • 原文地址:https://www.cnblogs.com/zcy_soft/p/1946619.html
Copyright © 2020-2023  润新知