Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 55 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
55
Dung lượng
3 MB
Nội dung
XML and Web Services 417 created phpDocumentor docblocks describing the functions or class methods, 14 to determine the XML-RPC prototypes. The caveat to using this approach is that you must use XML-RPC types in your docblocks to describe your parameters and return values. Zend_XmlRpc_Server, like all server classes in the Zend Framework, follows PHP’ s SoapServer API, which makes the interface consistent across the different protocol implementations. As an example, here’s a simple Math class with two methods, add and multiply, for which we can build a server: Math.class.php (excerpt) /** * Math methods */ class Math { /** * Return the sum of all values in an array * * @param array $values An array of values to sum * @return int */ public static function add($values) { return array_sum($values); } /** * Return the product of all values in an array * * @param array $values An array of values to multiply * @return int */ public static function multiply($values) { return array_product($values); } } 14 http://www.phpdoc.org/ Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 418 The PHP Anthology Now, let’s build the XML-RPC server, and for good measure, let’s also create a function for retrieving XML-RPC server information: zend_xmlrpc_serv.php (excerpt) require_once 'Zend/XmlRpc/Server.php'; require_once 'Math.class.php'; /** * Get some info from the server * * @return struct */ function getInfo() { return array( 'publisher' => 'SitePoint', 'title' => 'The PHP Anthology' ); } $server = new Zend_XmlRpc_Server(); // Math class methods will be available in the 'math' namespace $server->setClass('Math', 'math'); // getInfo() function will be available as server.getInfo $server->addFunction('getInfo', 'server'); // Handle a request echo $server->handle(); The Zend_XmlRpc_Server instance in this example will make three methods avail- able, math.add, math.multiply, and server.getInfo, in addition to several system methods that we can use to obtain information about the server. It will automatically check incoming requests to make sure they adhere to the various method signatures, throwing fault responses if they do not, and return the XML-RPC response along with any required headers. You don’t need to change your code to conform to the server class requirements; the server conforms to your code. You will need to write phpDocumentor docblocks for each method or function you’ll be serving, and ensure they contain @param and @return tags; the server uses these to create the method signatures, and compares the types and numbers of incoming parameters with those signatures to ensure the incoming request conforms to the definition. Additionally, the types specified with these tags should conform to XML- Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com XML and Web Services 419 RPC type definitions; for example, use struct for associative arrays, date- Time.iso8601 for dates, and so on. PHP’s Native XML-RPC Extension Serving XML-RPC with Zend_XmlRpc_Server is as easy as serving SOAP requests in PHP 5; simply register a class or function with the server, and handle it. But be- sides Zend_XmlRpc_Server, what options do we have? ext/xmlrpc can be used to build XML-RPC servers, too. We simply create an XML- RPC server using xmlrpc_server_create, register callbacks to XML-RPC method names, grab the request, handle it, and send the response back. As an example, let’ s try to serve the following method and function: ext_xmlrpc_serv.php (excerpt) /** * Math methods */ class Math { /** * Return the sum of all values in an array * * @param array $values An array of values to sum * @return int */ public static function add($method, $params) { return array_sum($params[0]); } } /** * Return the product of some values * * @param string $method The XML-RPC method name called * @param array $params Array of parameters from the request * @return int */ function product($method, $params) { return array_product($params); } Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 420 The PHP Anthology Now that we’ve created these definitions, we’ll register them with the XML-RPC server: ext_xmlrpc_serv.php (excerpt) $server = xmlrpc_server_create(); xmlrpc_server_register_method($server, 'math.add', array('Math', 'add')); xmlrpc_server_register_method($server, 'product', 'product'); Now we need to grab the request, dispatch it, and return a response: ext_xmlrpc_serv.php (excerpt) $request = file_get_contents('php://input'); $response = xmlrpc_server_call_method($server, $request, null); header('Content-Type: text/xml'); echo $response; If you examine this example closely, you’ll notice that functions and method calls have to follow a particular signature; specifically, they can only accept two argu- ments: the requested $method and the requested $params. This means that if you want to create an XML-RPC server using ext/xmlrpc, you must either write all your method handlers to conform to this specification, write wrappers for your existing methods, or write a dispatcher to dispatch method calls using the original parameter order—all of which activities are beyond the scope of this discussion. The easier approach is to use an XML-RPC server that creates this magic for you. PEAR’s XML_RPC2 and Zend_XmlRpc are two such implementations. Zend_XmlRpc makes XML-RPC a first-class OOP citizen, simplifying the process of making requests and serving responses, and allowing any function or class method to be used as a server handler. How can I consume SOAP web services? SOAP, originally an acronym for Simple Object Access Protocol, but now simply a protocol name, is, to quote the specification, “a lightweight protocol intended for exchanging structured information in a decentralized, distributed environment.” SOAP provides tremendous flexibility and extensibility. Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com XML and Web Services 421 Like the other protocols discussed in this section, SOAP uses XML to transfer messages between the client and server. The base message unit that’s transferred is an object. A server needs to specify the available methods and properties, and make that specification available to clients so that they can initiate requests. This specific- ation is achieved using a WSDL, the Web Services Description Language, specifica- tion. The SOAP and WSDL specifications are notoriously difficult to decipher. The gen- eral consensus among developers is to use WSDL development tools to create the WSDL from your application classes, and to use clients and servers provided in your language to conduct the actual SOAP communication. Fortunately, PHP 5 has native SoapClient and SoapServer classes, and tools are emerging for generating the WSDL. The topic of consuming SOAP-based web services is incredibly broad and we couldn’t possibly cover it in any great detail in this book, but here’s a gentle intro- duction. Solution Using the PHP 5 SoapClient class is incredibly easy: $client = new SoapClient($uriToWsdl, array('location' => $uriToSoapService)); $result = $client->SomeMethod($value1, $value2) There’s certainly much more to the SoapClient class, but that’s the basic usage: create a SoapClient instance by passing the URL to the WSDL specification, and the location of the SOAP service, as arguments to the SoapClient constructor, and start making calls. The SoapClient makes all the methods of the SOAP service available as PHP methods. What if you want to pull the results of a SOAP request into an object? No problem! You can easily map a SOAP response to a PHP class. Here’ s a hypothetical example that uses a book information service. The SOAP service provides a getBookInfo method. If we pass it an $id value, it will return a response representing a book with author, title, date, and publisher properties. This response is defined in the web service’s WSDL file as the type Book. And if we already have an object for Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com a book in our PHP application (let’ s call it MyBook), we can map the SOAP response type onto our own MyBook object. First, we define our MyBook class: class MyBook { public $author; public $title; public $date; public $publisher; } When we instantiate the SoapClient object, we add a classmap option that maps the WSDL Book type to our MyBook PHP class: $client = new SoapClient($uriToWsdl, array( 'location' => $uriToSoapService, 'classmap' => array('Book' => 'MyBook') )); Now, when we call the SOAP method that would normally return the SOAP object type, we receive an instance of our PHP class instead: $book = $client->GetBookInfo($id); // $book is a MyBook instance echo $book->title; When it binds a class to a SOAP response, SoapClient will set in the object any public properties for which it finds a match in the response. Because the returned object instance is a standard PHP object, you can also define methods for accessing or transforming the SOAP data in the class. Discussion Assuming that the remote service has a defined WSDL specification, making requests to SOAP services is tremendously easy in PHP 5. The flexibility to bind objects to responses can offer tremendous opportunities for working with remote data. If you’ve been afraid of SOAP before, yet you’re comfortable with OOP, there’s no need to be afraid any longer! The PHP Anthology422 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com XML and Web Services 423 How do I serve SOAP web services? You’ve dipped your toes in the SOAPy water by consuming some SOAP services in “How can I consume SOAP web services?”, and now you’re thinking that the next step is to create some of your own. You’ve got a number of classes that seem eligible; how can you expose their APIs publicly? Solution Serving SOAP is roughly as easy as the using the client: use SoapServer. The topic of creating SOAP-based web services is another broad area that we couldn’t possibly cover in any great detail in this book, but let’s get our bearings by looking a simple example. First, let’s define a class for a book with the original name of Book: class Book { public $author; public $title; public $date; public $publisher; /** * Constructor * * @param string $author * @param string $title * @param int $date * @param string $publisher * @return void public function __construct($author, $title, $date, $publisher) { $this->author = $author; $this->title = $title; $this->date = $date; $this->publisher = $publisher; } } With that out of the way, we can define an API for retrieving books with a class called BookService: Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com class BookService { /** * Retrieve book information and send * * @param int $id * @return Book */ public function GetBookInfo($id) { ⋮ perform some work and get some book details… $book = new Book($author, $title, $date, $publisher); return $book; } } Now let’s bind these classes to a SoapServer instance: $server = new SoapServer($uriToWsdl, array( 'encoding' => 'ISO-8859-1', 'actor' => $uriToSoapService, 'classmap' => array('Book' => 'Book') )); $server->setClass('BookService'); $server->handle(); That’s all there is to it; your BookService class’s GetBookInfo method is now ex- posed as a SOAP method, and will return Book instances to requests from SOAP clients. Discussion Serving SOAP has never been so easy as it is with PHP 5. But there’ s one more aspect to consider: what about the WSDL specification? It’s possible to use SOAP between PHP servers without using WSDL, but this ap- proach is problematic, because it means that many of the features of the SOAP client, such as the auto-discovery of available methods, won’t work. It then becomes the responsibility of the service developer to communicate the available methods to those consuming the services. Although generating your own WDSL may be a daunting task, given the complexity of the specification, many IDEs have tools for generating WSDL specifications based on the introspection of your classes. Another The PHP Anthology424 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com XML and Web Services 425 choice for generating WSDL specifications, and a newcomer on the scene, is Zend_Soap, from the Zend Framework. 15 This component contains the Zend_Soap_AutoDiscover class, which will generate a WSDL specification from a class using PHP’s own Reflection API. Here’s an example: $generator = new Zend_Soap_AutoDiscover('BookService'); $wsdl = $generator->handle(); From here, you can cache the generated WSDL specification, contained in the $wsdl variable, in a web-accessible location, then start to create servers and clients for it using SoapServer and SoapClient. How can I consume REST services? REST, or Representational State Transfer, is a newcomer on the web services scene, and has gained considerable popularity in the past few years. The ideas behind this architectural approach are simple: application state and functionality are separated into resources that can be addressed with a unique identifier, all resources share a consistent interface and standardized content types. As it happens, the Web is a great example of this style of application architecture. We can use the URL as the unique identifier for resources and the HTTP protocol as the consistent interface through which we access the resources. Finally, resources are represented by standardized content types—XML, HTML, and so on. 16 As an example, let’s consider a hypothetical REST service for books: ■ A GET request to http://example.com/books uses XML to return a list of books. ■ A POST request that contains XML book data and is made to the same URL will add a new book to the service. ■ Retrieving the XML for an individual book involves making an HTTP GET request to a slightly different URL that specifies a particular resource, such as http://example.com/books/php-anthology. 15 http://framework.zend.com/manual/en/zend.soap.html 16 A more detailed explanation can be found on Wikipedia, at http://en.wikipedia.org/wiki/Representational_State_Transfer. Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 426 The PHP Anthology ■ Editing the book involves sending XML book data via an HTTP PUT request to the same URL. ■ Sending an HTTP DELETE request to the URL would delete the resource. Such a service would be considered RESTful, that is, it would follow the principles of REST. Each resource has a unique identifier, its URL, and each resource has a consistent interface, HTTP, through which the request type describes the type of action being requested. Basically, REST makes use of the technology of the Web, unlike XMLRPC or SOAP, which use the Web simply as a means for sending commands. For example, in our REST API above, sending a GET request to http://example.com/books/php-anthology returns the XML representation of the book. If the book doesn’t exist, the service responds with a standard HTTP 404 Not Found response. In contrast, using an XMLRPC interface to the same service might require you open a connection to the service and make a method call to a getBook method, passing the book’ s identifying code, php-anthology, as an argument. If the book didn’t exist, the service would respond with an error message. The main difference between these two approaches is the use of HTTP to represent the intended action—GETting a book—and the meaningful URL that represents the book itself. In real-world circumstances, many browsers and HTTP clients still don’t implement PUT and DELETE, so all resource update and delete operations are completed via POST requests that use additional request parameters to represent the operation de- sired. While not entirely RESTful, the practice is widespread enough to be considered the standard approach. Modern REST services that use XML are common. Some REST services provide XML schemas so that consumers can easily determine how to get at the data they need or format their requests, while others simply provide API documentation. Solution By now, you should be well on your way to being able to handle any XML that’s thrown at you. We can use SimpleXML to parse REST responses, and SimpleXML, DOM, or XMLWriter to create requests (if a data payload is needed). Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... production/ tags/ 200 6-0 9- 1 9- PirateDayJargon/ 200 6-0 5-1 1-LifeUniverseEverything/ 200 6-0 4-0 1-AprilFools/ trunk/ On a day-to-day basis, you work in the repository trunk As you finish features or bug fixes, you merge them into the production branch You then preview this branch on your staging server, which is almost identical to the production server—it may even use the same data, pulled from the same web services... PHP Anthology CSS Anthology In our book service, the id attribute of each book can be used to retrieve the book’s details Here’s an example of the XML returned by a GET request to http://example.com/books /php- anthology: php- anthology PHP Anthology SitePoint... verified the changes, or your quality assurance team has reviewed the site and given its seal of approval, you create a tag You can then export the project files from this tag: Best Practices Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com $ svn export ➥ http://example.com/svn/project/tags/200 6-0 9- 1 9- PirateDayJargon ➥ 200 6-0 9- 1 9- PirateDayJargon svn export grabs code from the repository... function body… } 11 12 http://phpdoc.org/ http://java.sun.com/j2se/javadoc/ 4 49 450 The PHP Anthology Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Running this declaration through phpDocumentor is a fairly simple exercise: $ phpdoc -f login .php -t docs This action creates a documentation tree inside the docs directory, and parses only the login .php file The documentation generated... scribes the changes: $ svn copy branches/production tags/200 6-0 9- 1 9- PirateDayJargon ➥ -m 'Pirate Day Jargon version of site for Pirate Day' Discussion In most cases, day-to-day development will occur in the repository trunk When you’re ready to create a software release, create a branch From this point forward, changes in the trunk will not affect code in the release branch—unless you merge them manually... a GET request, the code takes the branch to listing all the books If two elements are present, the script assumes that the second element is the book name In this case, a POST request represents an update to the specific book and a GET request will display the named book For the book list and named-book information requests, simply generate or fetch the XML to return to the user In the case of new... 'http://example.com/books/' $id, null, true 427 428 The PHP Anthology Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com ); echo $book->title, ', published by: ', $book->publisher, "\n"; } For XML-based REST services, we can employ SimpleXML to do the heavy lifting of making the request, receiving the response, and parsing it In the example above, we retrieve the books list by instantiating a new... unmaintainable Many programmers in the PHP field are now recognizing the need to standardize and promote best practices Some of these best practices are PHP specific, such as the usage of tools like phpDocumentor for consistent documentation,1 or testing suites such as SimpleTest2 and PHPUnit.3 Other practices that are being promoted in the PHP community are more generic the use of revision control systems... exploding the path information of the incoming request into an array, and trimming the trailing / character It then tests how many elements are XML and Web Services Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com generated, and whether the first element is books If only one element is present, books, the script checks the request method If it’s a POST request, the code takes the. .. dividually check out the repository to their own working directories, and check in their changes as they’re completed Both systems have their benefits and downsides However, non-distributed systems are more commonly used in PHP projects, so they’re the type you’ll most likely run into Having a central repository allows you to designate a single location for the canonical version of the software you’re . Unregistered Version - http://www.simpopdf.com 420 The PHP Anthology Now that we’ve created these definitions, we’ll register them with the XML-RPC server: ext_xmlrpc_serv .php (excerpt) $server. <book id=" ;php- anthology& quot;> ;PHP Anthology& lt;/book> <book id="css -anthology& quot;>CSS Anthology& lt;/book> </books> In our book service, the id attribute. that many of the features of the SOAP client, such as the auto-discovery of available methods, won’t work. It then becomes the responsibility of the service developer to communicate the available