欢迎投稿

今日深度:

利用PHP创建由Oracle驱动的SOAP服务(1)(4)

创建BookManager 类

现在,您已经熟悉了用 PHP 实施 SOAP 服务的所有内容,下面我们来讨论数据库。出于本手册的需要,我创建了一个名为 BookManager 的类。该类的作用将与前面示例中的 math 类相同,除了要与数据库进行交互,并提供一个 SOAP 服务,以允许您执行一般维护并查询本教程开头描述的书籍表。具体而言,BookManager 类将实施以下要公开为 SOAP 调用的方法: 

addBook($isbn, $author, $title, $price); 
// Adds a Book to the database
delBook($isbn); // Deletes a book by ISBN number
findBookISBNByAuthor($author);
 // Returns an array of ISBN numbers of books written by a         
// specific author
findBookISBNByTitle($title); 
// Returns an array of ISBN numbers of books whose title 
// matches the substring provided
getBookByISBN($isbn); 
// Returns the details of the book identified by ISBN
listAllBooks(); 
// Returns an array of all ISBN numbers in the database

尽管该类本身有其他几个方法,但只有上述六个方法是声明的公共方法当然,除了构造函数以外),因而也是仅有的公开为 SOAP 服务的方法。虽然详细说明每个方法会超出本教程讨论范围特别是它们在形式上基本相同),但出于完整性需要,我们来看一下 delBook() 方法: 

/**
 * Delete a book from the database by ISBN
 *
 * @param string $isbn The ISBN serial number of the book to delete
 * 
 * @return mixed SOAP Fault on error, true on success
 */
public function delBook($isbn) {

$query = "DELETE FROM books
                WHERE isbn = :isbn";

$stmt = oci_parse($this->getDB(), $query);

if(!$stmt) {
throw new SoapFault(-1, "Failed to prepare query (reason: " .  
                                         oci_error($stmt) . ")");
}

oci_bind_by_name($stmt, "isbn", $isbn, 32);

if(!oci_execute($stmt)) {
oci_rollback($this->getDB());
throw new SoapFault(-1, "Failed to execute query (reason: " . 
                                          oci_error($stmt) . ")");
}

oci_commit($this->getDB());

return true;
}

对于那些熟悉用于 PHP 的 Oracle API 的开发人员来说,上述方法应该很简单。对于其余开发人员来说,我们从 oci_parse() 方法开始来探究该函数的某些关键点。该方法以字符串的形式接受 SQL 查询如果需要,在查询中包含每个变量的占位符),然后返回表示该查询的语句资源。在这里,该语句资源的占位符可以通过 oci_bind_by_name() 方法直接映射到 PHP 变量,该方法将接受语句、占位符名称、对应的 PHP 变量以及可选的当前最大列长度作为参数。一旦 PHP 将每个占位符绑定到一个 PHP 变量,就可以执行语句并获得结果了。当然,由于该操作是一个针对表的 write 操作,您可以通过将更改提交到数据库并返回成功状态,来成功完成函数执行。

为便于参考,下面是一个完整的 BookManager 类,以及使用该类公开 SOAP 服务的相应服务器脚本。 

* @author John Coggeshall <john@zend.com>
 * 
 * @throws SoapFault
 */
class BookManager {

private $objDB;

const DB_USERNAME="demo";
const DB_PASSWORD="password";
const DB_DATABASE="myoracle";

/**
 * Object Constructor: Establishes DB connection
 *
 */
function __construct() {

$this->objDB = oci_connect(self::DB_USERNAME,
                           self::DB_PASSWORD,
                           self::DB_DATABASE);
       
if($this->objDB === false) {
throw new SoapFault(-1, "Failed to connect to database backend (reason: " . 
                                         oci_error() . ")");
}
}

/**
 * Private method to return the DB connection and make sure it exists
 *
 * @return unknown
 */
private function getDB() {
if(!$this->objDB) {
throw new SoapFault(-1, "No valid database connection");
}

return $this->objDB;
}

/**
 * Add a new book to the database
 *
 * @param string $isbn The ISBN serial number for the book (32 char max)
 * @param string $author The name of the primary author (50 char max)
 * @param string $title The title of the book (50 char max)
 * @param float $price The price of the book in USD
 * 
 * @return mixed SOAP Fault on error, true on success
 */
public function addBook($isbn, $author, $title, $price) {

$query = "INSERT INTO books (isbn, author, title, price)
               VALUES (:isbn, :author, :title, :price)";

$stmt = oci_parse($this->getDB(), $query);

if(!$stmt) {
throw new SoapFault(-1, "Failed to prepare query (reason: "  . 
                                         oci_error($stmt) . ")");
}

// The numbers 32, 50, 50 are the max column lengths
oci_bind_by_name($stmt, "isbn", $isbn, 32);
oci_bind_by_name($stmt, "author", $author, 50);
oci_bind_by_name($stmt, "title", $title, 50);
oci_bind_by_name($stmt, "price", $price);

if(!oci_execute($stmt)) {
oci_rollback($this->getDB());
throw new SoapFault(-1, "Failed to execute query (reason: " . 
                                         oci_error($stmt) . ")");
}

oci_commit($this->getDB());

return true;
}

/**
 * Delete a book from the database by ISBN
 *
 * @param string $isbn The ISBN serial number of the book to delete
 * 
 * @return mixed SOAP Fault on error, true on success
 */
public function delBook($isbn) {

$query = "DELETE FROM books
                WHERE isbn = :isbn";

$stmt = oci_parse($this->getDB(), $query);

if(!$stmt) {
throw new SoapFault(-1, "Failed to prepare query (reason: " . 
                                          oci_error($stmt) . ")");
}

oci_bind_by_name($stmt, "isbn", $isbn, 32);

if(!oci_execute($stmt)) {
oci_rollback($this->getDB());
throw new SoapFault(-1, "Failed to execute query (reason: " .  
                                          oci_error($stmt) . ")");
}

oci_commit($this->getDB());

return true;
}

/**
 * Return a list of books with a specific substring in their title
 *
 * @param string $name The name of the author
 * 
 * @return mixed SOAP Fault on error, an array of ISBN numbers on success
 */
public function findBookISBNByTitle($title) {

$query = "SELECT isbn
            FROM books
           WHERE title LIKE :titlefragment";

$stmt = oci_parse($this->getDB(), $query);

if(!$stmt) {
throw new SoapFault(-1, "Failed to prepare query (reason: " . 
                                         oci_error($stmt) . ")");
}

$bindVar = "%$title%";

oci_bind_by_name($stmt, ":titlefragment", $bindVar, 50);

if(!oci_execute($stmt)) {
throw new SoapFault(-1, "Failed to execute query (reason: " .  
                                         oci_error($stmt) . ")");
}

$rows = array();

while($row = oci_fetch_array($stmt, OCI_ASSOC)) {
$rows[] = $row['ISBN'];
}

return $rows;
}

/**
 * Return a list of books written by a specific author
 *
 * @param mixed $author SOAP Fault on error, on array of ISBN numbers on success
 */
public function findBookISBNByAuthor($author) {

$query = "SELECT isbn
            FROM books
           WHERE author = :author";

$stmt = oci_parse($this->getDB(), $query);

if(!$stmt) {
throw new SoapFault(-1, "Failed to prepare query (reason: " . 
                                         oci_error($stmt) . ")");
}

oci_bind_by_name($stmt, ":author", $author, 50);

if(!oci_execute($stmt)) {
throw new SoapFault(-1, "Failed to execute query (reason: " . 
                                          oci_error($stmt) . ")");
}

$rows = array();

while($row = oci_fetch_array($stmt, OCI_ASSOC)) {
$rows[] = $row['ISBN'];
}

return $rows;
}

/**
 * Return a list of all ISBN numbers in the database
 *
 * @return array An array of ISBN numbers in the database
 */
public function listAllBooks() {

$query = "SELECT isbn FROM books";

$stmt = oci_parse($this->getDB(), $query);

if(!$stmt) {
throw new SoapFault(-1, "Failed to prepare query (reason: " . 
                                         oci_error($stmt) . ")");
}

if(!oci_execute($stmt)) {
throw new SoapFault(-1, "Failed to execute query (reason: " . 
                                         oci_error($stmt) . ")");
}

$rows = array();

while($row = oci_fetch_array($stmt, OCI_ASSOC)) {
$rows[] = $row['ISBN'];
}

return $rows;
}

/**
 * Return the details of a specific book by ISBN
 *
 * @param string $isbn The ISBN of the book to retrieve the details on
 * 
 * @return mixed SOAP Fault on error, an array of key/value pairs for the ISBN on  
 *               success
 */
public function getBookByISBN($isbn) {

$query = "SELECT *
            FROM books
           WHERE isbn = :isbn";

$stmt = oci_parse($this->getDB(), $query);

if(!$stmt) {
throw new SoapFault(-1, "Failed to prepare query (reason: " . 
                                          oci_error($stmt) . ")");
}

oci_bind_by_name($stmt, ":isbn", $isbn, 32);

if(!oci_execute($stmt)) {
throw new SoapFault(-1, "Failed to execute query (reason: " . 
                                         oci_error($stmt) . ")");
}

$row = oci_fetch_array($stmt, OCI_ASSOC);
return $row;
}
}

?>

<?php

require_once 'BookManager.class.php';

$server = new SoapServer("bookman.wsdl");
$server->setClass("BookManager");
$server->handle();

?>

 
 
 

用 PHP 创建 SOAP 客户端

前面已经说明了如何使用 PHP 创建 SOAP 服务,下面我们来看一下如何创建 SOAP 客户端,以供您的服务器与之通信。

尽管使用 PHP SOAP 实施通过 SOAP 执行远程过程调用的方法有很多,但我们建议的方法是使用 WSDL 文档。您已经生成了该文档以使 SOAP 服务运行,因此该文档已经存在。

要使用 PHP 创建 SOAP 客户端,您必须创建一个 SoapClient 类的实例,该类具有以下构造函数:

$client = new SoapClient($wsdl [, $options]);

对于 SoapServer 类,$wsdl 参数是要访问服务的 WSDL 文档的位置,可选参数 $options 是配置客户端连接的一组键/值对。以下是一些可用选项请参见 www.php.net/ 以获得完整列表):

◆soap_version:要使用的 SOAP 协议版本,其值为常量 SOAP_1_1 或 SOAP_1_2
◆login:如果在 SOAP 服务器上使用 HTTP 身份验证,这是要使用的登录名
◆password:如果在 SOAP 服务器上使用 HTTP 身份验证,这是要使用的密码
◆proxy_host:如果通过代理服务器连接,这是服务器的地址
◆proxy_port:如果通过代理服务器连接,这是代理监听的端口
◆proxy_login:如果通过代理服务器连接,这是登录时使用的用户名
◆proxy_password:如果通过代理服务器连接,这是登录时使用的密码
◆local_cert:如果连接到一个通过安全 HTTP (https) 通信的 SOAP 服务器,这是本地认证文件的位置
◆passphrase:与 local_cert 结合使用,以提供认证文件的密码短语如果有)
◆compression:如果设置为 true,PHP 将尝试使用压缩的 HTTP 请求与 SOAP 服务器通信
◆classmap:将 WSDL 数据类型映射到 PHP 类以便在客户端使用的一组键/值对

如果 PHP 中的 SOAP 客户端通过 WSDL 文档实例化,就可以使用返回的客户端对象调用在 SOAP 服务器上公开的方法就好像它们是自带 PHP 调用),并处理任何可能作为原生 PHP 异常发生的 SOAP 错误。例如,返回到原始 math SOAP 服务示例,以下是一个完整的 PHP SOAP 客户端:

<?php

    $client = new SoapClient
(“http://www.example.com/math.wsdl”);
    
    try {
        $result = $client->div(10,rand(0,5); 
// will cause a Soap Fault if divide by zero
        print “The answer is: $result”;
    } catch(SoapFault $f) {
        print “Sorry an error was caught 
executing your request: {$e->getMessage()}”;
    }
?>


www.htsjk.Com true http://www.htsjk.com/shujukukf/17235.html NewsArticle 创建BookManager 类 现在,您已经熟悉了用 PHP 实施 SOAP 服务的所有内容,下面我们来讨论数据库。出于本手册的需要,我创建了一个名为 BookManager 的类。该...
评论暂时关闭