歡迎您光臨本站 註冊首頁

基於 PHP5 面向對象特性的 PECL 擴展 Perl 與 PDO 編程

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  
PECL(PHP Extension Community Library)是 PHP5 的一個重要特性。它避免了以往繁多的 PHP 擴展安裝方式,採用了統一的安裝方法。其中的面向對象的嵌入式 Perl 擴展編程與統一數據訪問介面 PDO(PHP Data Objects)使得開發人員可以直接使用 Perl 的語言特性與優勢並獲得統一的資料庫訪問介面對 WEB 應用程序進行快速開發。在實例代碼中,您將看到一個簡單的基於 WEB 的伺服器網路連通性測試工具,同時應用 PHP Perl 擴展並結合 PDO 操作 DB2 資料庫進行基本介紹與演示

簡介

擁有更成熟面向對象語法的 PHP 5 發布之後,基於 PHP 面向對象新特徵的一些 PECL 擴展也得到了極大的發展。本文的主要目的就是通過一個簡單的應用展示兩個基於 PHP5 面向對象特性的 PECL 擴展的安裝部署及編程方法。





PECL

PECL 的全稱是 The PHP Extension Community Library ,是一個開放的並通過 PEAR(PHP Extension and Application Repository,PHP 擴展和應用倉庫)打包格式來打包安裝的 PHP 擴展庫倉庫。通過 PEAR 的 Package Manager 的安裝管理方式,可以對 PECL 模塊進行下載和安裝。與以往的多數 PEAR 包不同的是,PECL 擴展包含的是可以編譯進 PHP Core 的 C 語言代碼,因此可以將 PECL 擴展庫編譯成為可動態載入的 .so 共享庫,或者採用靜態編譯方式與 PHP 源代碼編譯為一體的方法進行擴展。PECL 擴展庫包含了對於 XML 解析,資料庫訪問,郵件解析,嵌入式的 Perl 以及 Pthyon 腳本解釋器等諸多的 PHP 擴展模塊,因此從某種意義上來說,在運行效率上 PECL 要高於以往諸多的 PEAR 擴展庫。

在使用 PECL 對 PHP 進行擴展安裝過程中,需要用戶熟悉 PEAR 包的安裝方法以及 pear 命令。使用 PEAR Package Manager 可以直接下載,編譯並安裝 PECL 擴展庫至 PHP 的擴展目錄中,用戶需要自行將擴展庫的支持在 php.ini 文件中加以配置,或直接使用 dl() 函數在運行時進行動態載入以使用 PECL 的擴展庫功能。

關於 PEAR Package Manager 詳細的使用方法,請參閱 http://pear.php.net 上的相關文檔。本文也將在下面的示例中給出使用 PEAR Package Manager 進行 PHP 的 PECL 擴展庫安裝的示例。





嵌入式 Perl 解釋器擴展

PHP 的 Perl 擴展允許在 PHP 代碼中直接使用 Perl 代碼。這實際是一個內嵌的 Perl 的解釋器,能夠在 PHP 和 Perl 之間進行數據的交換。目前該擴展僅支持從 PHP 到 Perl 的單向介面,在將來會實現雙向介面。目前 PHP 的 Perl 擴展允許程序員使用 PHP 腳本做以下事情:

  • 載入並執行 Perl 文件
  • 執行 Perl 代碼
  • 訪問和修改 Perl 變數
  • 調用 Perl 函數
  • 初始化 Perl 對象
  • 訪問 Perl 對象的屬性
  • 調用 Perl 對象的方法

所有的這些特徵都是通過一個簡單的 API 類—— Perl 實現的。PHP 的 Perl 擴展的安裝部署方法將在後面介紹,這裡先來討論該擴展的使用方法。從 PHP 中訪問 Perl 的解釋器,首先需要創建一個 Perl 類的實例。


清單 1. 初始化 Perl 對象
<?php      $Perl = new Perl();  ?>  

上面的代碼創建了一個 Perl 解釋器的實例,該擴展允許在 PHP 代碼環境中同時創建這個解釋器的多個實例,但是他們在內部將使用同一個解釋器,因此所有的變數和代碼都將通過實例共享。對象 $perl 可以用來訪問和修改 Perl 變數,調用 Perl 函數,執行 Perl 代碼,載入並執行外部 Perl 文件等。其中外部文件可以通過 Perl:require() 方法載入。這個函數不返回任何值,如果要載入的 Perl 文件不存在或無效,這將會導致拋出 PHP 異常。

清單 2. Perl 實例操作示例

<?php

$perl = new Perl();

$perl->require(test.pl); //load external file – test.pl

var_dump($perl->x); // print scalar Perl variable - $x

var_dump($perl->array->x); // print array Perl variable - @x

var_dump($perl->hash->x); // print hash Perl variable - %x

$perl->func(); // call Perl function 'func' in void context

$x = $perl->func(); // call Perl function 'func' in scalar context

$y = $perl->array->func(); // call Perl function 'func' in array context

$y = $perl->hash->func(); // call Perl function 'func' in hash context

?>

執行 Perl 代碼,Perl 代碼可以通過 eval() 來執行,當要執行的 Perl 代碼出現錯誤時拋出PHP異常。


清單 3. 執行 Perl 代碼示例
<?php      $perl = new Perl();      $perl->eval('use Digest::MD5');//load perl class MD5      echo $perl->{'Digest::MD5::md5_hex'}('perl2php');      var_dump($perl->md5_hex(“Hello”));      $perl->eval('require "TEST.pm";');//load a perl class file      echo $perl->eval($x.'+'.$y.';');  // caculate and print the result of x+y      $perl->eval('$z='.$x.'+'.$y.';');       echo $z;      $perl->eval(‘                  sub sum{                      my $x = shif(@_);                      foreach my $y (@_){                          $total + =$y;                      }                      return $total                  }                  ’);      echo $perl->eval(“sum(1,2,3,4)”).”.”;  ?>  

默認情況下 Perl 代碼在標量上下文中被執行,但是也可以指定其在 array 或者 hash 上下文中執行


清單 4. 在 array 和 hash 上下文執行 Perl 代碼
<?php      $perl = new Perl();      $perl->eval('("a","b","c")');                  // eval in void context      var_dump($perl->eval('("a","b","c")'));        // eval in scalar context      var_dump($perl->array->eval('("a","b","c")')); // eval in array context      var_dump($perl->hash->eval('("a","b","c")'));  // eval in hash context  ?>  

除此之外,也可以在 PHP 腳本中使用 Perl 對象,Perl 本身是一種面向對象的語言,但是對於類的定義沒有具體的語法,在 Perl 中類可以看做是一個包,類的方法可以簡單的認為是包中提供的一些函數,這些函數把該對象的引用作為第一個參數。Perl 擴展允許開發人員在 PHP 腳本中初始化 Perl 對象,並允許直接訪問該對象的屬性和方法。在PHP 中使用 Perl 對象,同樣需要使用 Perl() 這個構造函數,但與前面的方法不同的是,需要傳遞參數給該構造函數。語法如下:


清單 5. 嵌入式的 Perl 解釋器對象
new Perl($perl_class_name[, $constructor = "new"[perl_para,…]])  

其中第一參數是 Perl 的類(包)名,第二個參數是構造函數的名字(可選)。如果有其他參數,這些參數將被傳遞給 Perl 的構造器。如果第二個參數被省略,默認的構造函數 new() 將被調用。

在 PHP 的腳本中初始化一個 Perl 對象之後便可以跟使用 PHP 自身的對象一樣進行使用,唯一的不同點是方法調用的上下文不一樣,在默認情況下,方法是在標量 scalar 上下文中被調用。要想在 array 或者 hash 上下文中進行調用,可以參照前面的方法:不直接通過 Perl 對象調用該方法,而應該通過一個具體的屬性 array 或者 hash 進行調用。此外初始化 Perl 對象之後還可以在對象之間進行複製操作。


清單 6. 對象操作示例
<?php        $x = new Perl("Test");        $y = new Perl("Test","Test",$x);        $z = clone $y;        echo $z->property;        echo $z->method(1,2,3); // call method "f" in void context        var_dump($x->method(1,2,3));        // call method in scalar context        var_dump($x->array->method(1,2,3)); // call method  in array context        var_dump($x->hash->method(1,2,3));  // call method in hash context  ?>  

在上面的實例代碼中 Test 是一個 Perl 類,在 PHP 代碼環境中可以用 require() 的方法將其包文件從外部引入也可以在 PHP 腳本中利用 Perl 對象的 eval 函數直接構造這樣一個 Perl 類,實例的第一行將調用 Test 類中的 new 方法構造 Test 對象,而第二行將調用 Test 類中的 Test 方法構造 Test 對象。





統一的數據訪問介面PDO

PDO(PHP Data Objects) 擴展為 PHP 訪問資料庫定義了一個輕量級的、一致性的介面,它提供了一個數據訪問抽象層,這樣,無論使用什麼資料庫,用戶都可以通過統一的函數執行來查詢和獲取數據。注意,你並不能使用 PDO 擴展本身執行任何資料庫操作,必須使用一個 database-specific PDO driver (針對特定資料庫的 PDO 驅動)訪問資料庫伺服器。

目前 PDO 支持如表1中資料庫操作介面:


表 1. 支持 PDO 的驅動及相應的資料庫列表
驅動程序名 所支持的資料庫伺服器
PDO_DBLIB FreeTDS / Microsoft SQL Server / Sybase
PDO_FIREBIRD Firebird/Interbase 6
PDO_IBM IBM DB2
PDO_INFORMIX IBM Informix Dynamic Server
PDO_MYSQL MySQL 3.x/4.x/5.x
PDO_OCI Oracle Call Interface
PDO_ODBC ODBC v3 (IBM DB2, unixODBC and win32 ODBC)
PDO_PGSQL PostgreSQL
PDO_SQLITE SQLite 3 and SQLite 2

PDO 並不提供資料庫抽象,它並不會重寫 SQL 或提供資料庫本身缺失的功能,如果用戶需要這種功能,就必須使用一個更加成熟的抽象層。PDO 是隨 PHP 5.1 發行,在PHP 5.0的 PECL 擴展中也可以使用。PDO 需要 PHP 5 核心面向對象特性的支持,所以它無法運行於之前的PHP 版本。

PDO 的安裝部署方法將會在後面的章節介紹,此處先介紹 PDO 的使用。

連接和連接管理

資料庫連接的建立可以通過創建一個 PDO 基類的實體實現,開發人員不用關心需要使用的是那個驅動,在代碼中只需要使用 PDO 的類名。構造函數接受一個參數來表明數據源(也就是通常所知的 DSN)。另外還有三個參數是可選的,如果資料庫伺服器的連接需要提供用戶名和密碼,則需要在構造函數中指定;在該構造函數中,同時還可以通過第三個可選參數傳遞連接類型等的信息。


清單 7. 建立 PDO 連接(以 DB2 Server為例)
<?php      function Connect()      {          try{              $dbh = new PDO(‘odbc:test’,‘user’,‘password’,                  array(PDO_ATTR_PERSISTENT =) true));          } catch(PDOException $e) {              echo 'Connection failed: ' . $e->getMessage();              die();          }          return $dbh;      }  ?>  

odbc:test 告訴 PDO 它所應該使用的 ODBC 驅動程序,並且應該使用 "test" 資料庫。如果使用一個驅動程序管理器,那麼可以用一個 ODBC 級數據源名稱替代 "test"。在冒號字元之後可以指定任何有效的 ODBC 數據源連接字元串。接下來分別是用來連接資料庫的用戶名和密碼。通過設定 PDO_ATTR_PERSISTENT 的值為 true 可以建立一個到資料庫的持久連接,默認情況下不指定此參數建立的連接在腳本運行完畢或者所有對該 $dbh 的應用都被是釋放的時候連接就會被斷開。在某些情況應用程序的設計者只希望建立一次連接,以後對該資料庫所有的訪問操作都通過該連接實現。這時候就可以建立持久連接,持久連接建立後會被緩存並且在其他的資料庫操作腳本訪問該數據源的時候被重用。

斷開連接

默認情況下,當建立的連接是非持久連接時候,當腳本結束時候連接將會斷開,也可以通過顯性的將 $dbh 變數設置為 null 來斷開連接。


清單 8. 斷開 PDO 連接
<?php      function Disconnect($dbh)      {          $dbh = null;      }  ?>  

執行資料庫操作

建立了與資料庫的連接之後就可以對資料庫進行 SQL 查詢操作,對於無返回結果集的資料庫操作(例如刪除,更新,插入等) PDO 通過一個統一的函數 exec() 來實現,這個函數的返回值通常是資料庫操作影響的行數,以刪除為例,函數的返回結果是刪除的行數。而對於需要返回數據結果集的查詢操作則通過 query() 函數來實現。它將返回一個 PDOStatement 類型的結果集合。對於 PDOStatement 類型的結果集可以用它的各種操作方法(例如 fetch() 等)來操作結果集裡面的數據。


清單 9. 執行資料庫操作
<?php  //issues a SQL statement and returns the number of affected rows.  function Execute($execStr)  {      try{          $dbh = Connect();//引用清單1中的方法          $result = $dbh->exec($execStr);      } catch (Exception $e) {              }      return $result;  }  //issues a SQL statement and returns a result set.  function Query($queryStr)  {      try{          $dbh = Connect();//引用清單1中的方法          $result = $dbh->query($queryStr);      } catch (Exception $e) {      }      return $result;  }  ?>  

事務和自動提交

PDO 的事務操作以自動提交模式運行,也就是說如果資料庫支持事務,那麼所運行的每一個查詢都有它自己的隱式事務,如果資料庫不支持事務,每個查詢就沒有這樣的事務。如果需要啟動一個事務操作,必須使用 PDO::beginTransaction() 方法來啟動。這裡需要注意的是:如果底層驅動程序不支持事務,那麼將拋出一個 PDOException。在一個事務中,可以使用 PDO::commit() 或 PDO::rollBack() 來結束該事務,這取決於事務中運行的代碼是否成功。


清單 10. 運用事務操作進行批處理
<?php      //issues a set of SQL statement during a transaction      function Execute (array $tranStr)      {          try{              $dbh = Connect();//引用清單1中的方法              $dbh->beginTransaction();              foreach($transStr as $stateStr)              {                  $dbh->exec($stateStr);              }              $dbh->commit()          } catch (Exception $e) {              $dbh->rollBack();          }          return $result;      }  ?>  

在上面的函數中所要執行的一系列 SQL 命令包括在 beginTransaction() 和 commit() 調用中,可以保證在更改完成之前,其他人無法看到更改。如果發生了錯誤,catch 塊可以回滾事務開始以後發生的所有更改。這樣可以有效的保證數據的一致性,在需要同步進行操作的數據更新中有重要應用。當腳本結束或當一個連接即將被關閉時,如果有一個未完成的事務,那麼 PDO 將自動回滾該事務。

預處理語句

首先需要解釋一下預處理語句,通常將預處理語句看作要運行的 SQL 的一種編譯過的模板,它可以使用變數參數進行定製。以運行一個重複插入數據為例,當往一個表中反覆插入不同的數據的時候,使用預處理語句只需要編譯一次,每次插入的時候只需要將變數用具體的參數取代即可。這可以在很大程度上提高資料庫的性能。大部分成熟的資料庫都支持預處理語句,即使驅動程序不支持預處理語句,PDO 也將模擬預處理語句。


清單 11. 使用預處理語句
<?php      $dbh = Connect();      $prepareStatement = $dbh->prepare(“INSERT INTO STUDENT (id,name) VALUES (:id,:name)”);            //bind the placeholder with a specify variable.      $prepareStatemnet->bindParam(‘:id’, $id);      $prepareStatement->bindParam(‘:name’, $name);            //insert records.      $id = ‘1’;      $name = ‘user1;      $prepareStatement->execute();      $id = ‘2’;      $name = ‘user2;      $prepareStatement->execute();  ?>  





示常式序:一個簡單的網路連通性測試工具

在這個簡單的示常式序中,使用 Perl 編寫一個檢查指定的伺服器是否可以通過操作系統 ping 命令測試網路連通的函數,並通過 PHP 調用該方法獲取測試結果,同時將測試的結果存入基於 DB2 的資料庫中。在這個基於 WEB 的示常式序中,對於測試伺服器網路是否可連接的 Perl 語言代碼在附件的實例代碼中,讀者可以下載閱讀。本文將不對該部分代碼做解釋,而將主要的精力放在描述 PHP 調用 Perl 代碼的方法和 PDO 操作資料庫的方法上。讀者可以在本文的代碼下載中獲取到完整的該程序的源代碼。

開發環境的搭建

本演示常式由數個樣本程序組成,並使用了下列組件及開發測試工具:

操作系統:RedHat Enterprise Linux Server 5.0

  • WEB 伺服器:Apache 2.2.8
  • 資料庫伺服器:DB2 Server Enterprise Edition 9
  • PHP:5.0.0/5.2.6
  • Perl:5.8.0

對於 PHP 和 Apache 的安裝部署在本文中不做重複介紹,以下僅介紹 PDO 和 Perl 擴展的安裝與部署方法。

PHP Perl擴展的安裝與部署

PHP 的 Perl 擴展可以在 PECL 的網站http://pecl.php.net/package/perl獲得下載。為了正確安裝和使用該擴展,操作系統的軟體環境必須滿足以下需求:

  • PHP 5.0.0 RC2 以上版本
  • Perl 5.8.0 以上版本

編譯擴展文件,PHP_PREFIX 和 PERL_PREFIX 必須指向 PHP 和 Perl 的安裝路徑。

#export PHP_PREFIX="/usr"  #export PERL_PREFIX="/usr"  #$PHP_PREFIX/bin/PHPize  #./configure --with-Perl=$PERL_PREFIX --with-PHP-config=$PHP_PREFIX/bin/PHP-config  #make  

安裝(這一步需要根用戶特權)

#make install  

在 php.ini 中添加 Perl 擴展 (這一步需要根用戶特權)

extension=Perl.so  

PDO 擴展的安裝部署

PHP 5.1 發布時附帶了 PDO,但是也可以通過 PECL 這個 PHP 擴展庫來結合使用 PDO 和 (1) PHP 5.0.3 及以上版本的安裝。

在示例應用程序的開發中,所使用的是一個 DB2 資料庫伺服器。需要注意的一點是在安裝PDO 時需要 ODBC 驅動,這就需要在本地安裝有 DB2 管理客戶機,否則編譯將失敗。

在 PHP 5.0.3 及以上版本上通過 PECL 進行安裝

默認情況下,PHP 將安裝 "PEAR" 包管理系統。為了成功地安裝 PDO,需要升級到 PEAR 1.3.5(需要跟用戶特權);使用以下命令

#pear  upgrade PEAR  

接下來就可以安裝 PDO 了(同樣需要根用戶特權):

#pear install PDO

安裝完 PDO 核心后,為了使之生效,需要在 php.ini 文件中添加以下內容:

extension=pdo.so  

接下來需要安裝用於 PDO 的 ODBC 驅動程序

#pear install PDO_ODBC   

按照提示輸入 ODBC 驅動程序的類型和驅動程序的位置,在示常式序中使用的是 DB2 伺服器,如果採用 DB2 的默認安裝選項,可以直接輸入 ibm-db2,如果選擇了不同的安裝位置,就要用實際的位置替換 /home/db2inst1/sqllib。由於 PEAR 不會為用戶配置 PECL 擴展,因此在安裝完成後需要將驅動程序添加到 php.ini 文件中,從而在PHP中正確載入驅動程序。確保將下面的內容添加在之前所添加的 pdo.so 這一行之後,否則 PHP 將不能正確地初始化。

extension=pdo_odbc.so

(2) PHP 5.1及以上版本的安裝

PHP 5.1 發布時附帶了 PDO,為獲得 DB2 支持,只需在編譯 PHP 時將下面的開關添加到配置行。

#tar xzvf php-5.2.6.tar.gz  #cd php-5.2.6  #./configure –with-pdo-odbc=ibm-db2,/home/db2inst1/sqllib --with-apxs2=/usr/sbin/apxs  #make  #make install  

安裝完畢后,應該完全重新啟動 WEB 伺服器,以確保 PHP 裝載新的擴展,這樣就可以開始使用 PDO 了。如果您使用的是 UNIX 平台,那麼需要獲得 DB2 客戶機的 DB2 實例環境,以便正確地初始化,可以通過運行命令 source /home/db2inst1/sqllib/db2profile 來完成。

示常式序

該示常式序的流程和結構如下圖所示,下面將分別介紹各個部分的功能及實現方法。讀者可以在本文附帶的示例代碼中


圖 1. 示常式序總體結構

測試伺服器連通性的 Perl 模塊(Connectivity Test Module)

代碼文件:SERVERCHECK.pm

該模塊採用 Perl 編寫,使用 Perl 的系統調用函數 system() 執行 ping 命令,將標準輸出輸入到日誌文件中,然後利用 Perl 的正則處理能力校驗文件中的內容,從來判斷伺服器的是否能通過 ping 命令檢測遠端伺服器的網路是否連通。在該函數中所調用的validate_cmd_response()函數會調用system()系統函數並捕獲標準輸出,同時驗證標準輸出中是否匹配指定字元串。


清單 12. 判斷遠端伺服器網路連接性
sub server_is_connective {      my( $class) = shift @_;      my( $serverIp ) = @_;      my( $pingOption,$validValue);      $pingOption = '-c 2';      $validValue = ("2 packets transmitted, 2 received, 0% packet loss");      my($rtnValue) = &validate_cmd_response("ping $pingOption $serverIp",$validValue);      print $rtnValue;  }    sub validate_cmd_response{      my( $cmd,$pValid) = @_;      if( $cmd ){          my ( @stdoutValue ) = &x_execute_cmd( $cmd );              if ( grep( /$pValid/i, @stdoutValue ) ){              return 1;          }      }      return 0;  }  

PHP-Perl函數連接器(PHP-Perl Connector)

代碼文件:Connector.php

該部分實現一個是從 Perl 介面向 PHP 介面轉化的連接方法,在該部分中將 Perl 類中的方法轉化成PHP函數。


清單 13. PHP 調用 Perl
<?php      public function php2perl($func_name,array $para_array)      {          $func_str = $func_name."(\"\",";          $conn_str = "";          foreach($para_array as $para)          {//add all parameters              $func_str.= $conn_str."\"".$para."\"";              $conn_str = ",";          }          $func_str .= ");";          try {              ob_start();              $perl = new Perl();              //push the complete directory of perl file into @INC variable              $perl->eval('push(@INC,"/web/www.domain.com/docs/sample");');              $perl->eval('use SERVERCHECK');              $result = $perl->eval("SERVERCHECK::$func_str");              $out = ob_get_contents();              ob_end_clean();          } catch(PerlException $excep){              echo "Perl error".$excep->getMessage()."\n";              $out = "Perl error";          }          return $out;      }  ?>  

在實例代碼中只給出了一個轉換,如果 Perl 代碼中有其他的介面,也可以按照相同的方式將其轉化為 PHP 介面。只要在方法中給出要調用的 Perl 方法的名字,並將要傳遞的參數放到一個數組中作為第二個參數,然後調用 php2perl() 方法就可以實現。在所定義的 PHP 函數 is_server_connective() 中,通過直接調用 php2perl() 函數,可以直接獲得 Perl 函數 server_is_connective() 的返回結果。


清單 14. 使用php2perl的方法將Perl函數加以封裝
public function is_server_connective($server)  {      $para = array($server);      $result = $this->php2perl('server_is_connective',$para);      return $result;  }  

資料庫操作模塊(DB Operation Module)

代碼文件:

PdoOpt.php(PDO 通用操作類)

GeneralDbOpt.php(資料庫通用操作類)

ServerData.php(serversample 表操作類)

該模塊實現應用程序跟 DB2 伺服器的通信,通過這個部分可以將資料庫中需要測試網路連接的伺服器信息(主機名和地址)查詢出來,在完成伺服器連通性測試之後將測試結果更新回資料庫中。在這裡將 PDO 的基本操作單獨抽象為一個類 PdoOpt,當需要更換資料庫的時候可以在該文件中更改相應的資料庫驅動等信息即可。基於此類可以建立出對資料庫數據進行增刪改查等基本的操作的資料庫通用操作類 GeneralDbOpt,下面的代碼演示了該類使用 PdoOpt 類執行數據查詢的方法。


清單 15. 通過 PdoOpt 從指定表中查找指定id的數據結果
public function select($table,$select_id)  {     $sel_str = "select *  from $table ";     if($select_id !== ""&& $select_id !== null)      {         $sel_str .= " where id =".$select_id;     }     try{         if($result = $this->pdoOpt->Query($sel_str))         {             $rtn_value = $result->fetch(PDO::FETCH_ASSOC);         }     } catch(Exception $e) {         echo $e->getMessage();     }     return $rtn_value;  }  

在此類基礎之上構建對於具體表的操作方法。應用中以操作 serversample 表為例實現了一個 ServerData 類。所有對該表的操作都在該類中實現。以獲取資料庫中所有的伺服器信息為例演示如何使用 GeneralDbOpt 類


清單 16. 從資料庫中獲取伺服器列表
public function get_server_list()  {      $fields = array('id','name');      $tables = array ($this->table);      return $this->general_db_opt->select_all($tables,$fields,'');  }  

資料庫說明:資料庫表中只有一個簡單的演示用表 serversample,該表中有 id,name,ip,status 四個欄位,分別代表伺服器的標識,主機名,IP地址和狀態信息。具體信息可以參看附件中的資料庫表結構信息。

頁面展現模塊(Web View)

為了更好更清晰的展現該示例應用程序的邏輯結構,在該部分簡單採用了 Smarty 的模板技術,避免將PHP 代碼夾雜到 HTML 代碼中。只使用該技術將資料庫中查出的伺服器信息呈現到頁面上,在 Smarty 的網站 http://smarty.php.net/ 可以下載安裝該引擎。


清單 17. Smarty 簡單示例
<?php      require('/usr/local/lib/php/Smarty/Smarty.class.php');      define('_SMARTY_ROOT','/web/www.domain.com/Smarty');        $smarty = new Smarty();      $smarty->template_dir = _SMARTY_ROOT."/templates";      $smarty->compile_dir = _SMARTY_ROOT."/templates_c";      $smarty->cache_dir = _SMARTY_ROOT."/cache";      $smarty->config_dir = _SMARTY_ROOT."/configs";      $smarty->right_delimiter = '}>';      $smarty->left_delimiter = '<{';  ?>  

應用程序邏輯

首先獲取伺服器的信息並顯示到頁面上,可以通過 get_server_list() 方法獲取到伺服器的信息,然後將其賦值給 server_info 變數,Smarty 在頁面上控制如何展現這些伺服器信息。


清單 18. 從資料庫中獲取所有伺服器的信息並在 WEB 頁面呈現
<?php      require('main.php');      require('ServerData.php');      $serverData = new ServerData();      $server_info = $serverData->get_server_list();      $smarty->assign('server_info',$server_info);      $smarty->display('serverping.tpl');  ?>  

當點擊頁面上的 Test 按鈕時候會獲取當前按鈕所指定的伺服器的 id,從而獲得所需要測試連通性的伺服器信息,通過調用 connector 的方法測試,測試完畢后調用 ServerData 的更新方法將測試結果更新進資料庫中指定 id 的伺服器信息中。


清單 19. 從 PHP 端測試伺服器連通性並將數據更新至資料庫中
<?php      require_once('Connector.php');      require_once('ServerData.php');      require('main.php');            $server_id = 
PECL(PHP Extension Community Library)是 PHP5 的一個重要特性。它避免了以往繁多的 PHP 擴展安裝方式,採用了統一的安裝方法。其中的面向對象的嵌入式 Perl 擴展編程與統一數據訪問介面 PDO(PHP Data Objects)使得開發人員可以直接使用 Perl 的語言特性與優勢並獲得統一的資料庫訪問介面對 WEB 應用程序進行快速開發。在實例代碼中,您將看到一個簡單的基於 WEB 的伺服器網路連通性測試工具,同時應用 PHP Perl 擴展並結合 PDO 操作 DB2 資料庫進行基本介紹與演示

簡介

擁有更成熟面向對象語法的 PHP 5 發布之後,基於 PHP 面向對象新特徵的一些 PECL 擴展也得到了極大的發展。本文的主要目的就是通過一個簡單的應用展示兩個基於 PHP5 面向對象特性的 PECL 擴展的安裝部署及編程方法。





PECL

PECL 的全稱是 The PHP Extension Community Library ,是一個開放的並通過 PEAR(PHP Extension and Application Repository,PHP 擴展和應用倉庫)打包格式來打包安裝的 PHP 擴展庫倉庫。通過 PEAR 的 Package Manager 的安裝管理方式,可以對 PECL 模塊進行下載和安裝。與以往的多數 PEAR 包不同的是,PECL 擴展包含的是可以編譯進 PHP Core 的 C 語言代碼,因此可以將 PECL 擴展庫編譯成為可動態載入的 .so 共享庫,或者採用靜態編譯方式與 PHP 源代碼編譯為一體的方法進行擴展。PECL 擴展庫包含了對於 XML 解析,資料庫訪問,郵件解析,嵌入式的 Perl 以及 Pthyon 腳本解釋器等諸多的 PHP 擴展模塊,因此從某種意義上來說,在運行效率上 PECL 要高於以往諸多的 PEAR 擴展庫。

在使用 PECL 對 PHP 進行擴展安裝過程中,需要用戶熟悉 PEAR 包的安裝方法以及 pear 命令。使用 PEAR Package Manager 可以直接下載,編譯並安裝 PECL 擴展庫至 PHP 的擴展目錄中,用戶需要自行將擴展庫的支持在 php.ini 文件中加以配置,或直接使用 dl() 函數在運行時進行動態載入以使用 PECL 的擴展庫功能。

關於 PEAR Package Manager 詳細的使用方法,請參閱 http://pear.php.net 上的相關文檔。本文也將在下面的示例中給出使用 PEAR Package Manager 進行 PHP 的 PECL 擴展庫安裝的示例。





嵌入式 Perl 解釋器擴展

PHP 的 Perl 擴展允許在 PHP 代碼中直接使用 Perl 代碼。這實際是一個內嵌的 Perl 的解釋器,能夠在 PHP 和 Perl 之間進行數據的交換。目前該擴展僅支持從 PHP 到 Perl 的單向介面,在將來會實現雙向介面。目前 PHP 的 Perl 擴展允許程序員使用 PHP 腳本做以下事情:

  • 載入並執行 Perl 文件
  • 執行 Perl 代碼
  • 訪問和修改 Perl 變數
  • 調用 Perl 函數
  • 初始化 Perl 對象
  • 訪問 Perl 對象的屬性
  • 調用 Perl 對象的方法

所有的這些特徵都是通過一個簡單的 API 類—— Perl 實現的。PHP 的 Perl 擴展的安裝部署方法將在後面介紹,這裡先來討論該擴展的使用方法。從 PHP 中訪問 Perl 的解釋器,首先需要創建一個 Perl 類的實例。


清單 1. 初始化 Perl 對象
<?php      $Perl = new Perl();  ?>  

上面的代碼創建了一個 Perl 解釋器的實例,該擴展允許在 PHP 代碼環境中同時創建這個解釋器的多個實例,但是他們在內部將使用同一個解釋器,因此所有的變數和代碼都將通過實例共享。對象 $perl 可以用來訪問和修改 Perl 變數,調用 Perl 函數,執行 Perl 代碼,載入並執行外部 Perl 文件等。其中外部文件可以通過 Perl:require() 方法載入。這個函數不返回任何值,如果要載入的 Perl 文件不存在或無效,這將會導致拋出 PHP 異常。

清單 2. Perl 實例操作示例

<?php

$perl = new Perl();

$perl->require(test.pl); //load external file – test.pl

var_dump($perl->x); // print scalar Perl variable - $x

var_dump($perl->array->x); // print array Perl variable - @x

var_dump($perl->hash->x); // print hash Perl variable - %x

$perl->func(); // call Perl function 'func' in void context

$x = $perl->func(); // call Perl function 'func' in scalar context

$y = $perl->array->func(); // call Perl function 'func' in array context

$y = $perl->hash->func(); // call Perl function 'func' in hash context

?>

執行 Perl 代碼,Perl 代碼可以通過 eval() 來執行,當要執行的 Perl 代碼出現錯誤時拋出PHP異常。


清單 3. 執行 Perl 代碼示例
<?php      $perl = new Perl();      $perl->eval('use Digest::MD5');//load perl class MD5      echo $perl->{'Digest::MD5::md5_hex'}('perl2php');      var_dump($perl->md5_hex(“Hello”));      $perl->eval('require "TEST.pm";');//load a perl class file      echo $perl->eval($x.'+'.$y.';');  // caculate and print the result of x+y      $perl->eval('$z='.$x.'+'.$y.';');       echo $z;      $perl->eval(‘                  sub sum{                      my $x = shif(@_);                      foreach my $y (@_){                          $total + =$y;                      }                      return $total                  }                  ’);      echo $perl->eval(“sum(1,2,3,4)”).”.”;  ?>  

默認情況下 Perl 代碼在標量上下文中被執行,但是也可以指定其在 array 或者 hash 上下文中執行


清單 4. 在 array 和 hash 上下文執行 Perl 代碼
<?php      $perl = new Perl();      $perl->eval('("a","b","c")');                  // eval in void context      var_dump($perl->eval('("a","b","c")'));        // eval in scalar context      var_dump($perl->array->eval('("a","b","c")')); // eval in array context      var_dump($perl->hash->eval('("a","b","c")'));  // eval in hash context  ?>  

除此之外,也可以在 PHP 腳本中使用 Perl 對象,Perl 本身是一種面向對象的語言,但是對於類的定義沒有具體的語法,在 Perl 中類可以看做是一個包,類的方法可以簡單的認為是包中提供的一些函數,這些函數把該對象的引用作為第一個參數。Perl 擴展允許開發人員在 PHP 腳本中初始化 Perl 對象,並允許直接訪問該對象的屬性和方法。在PHP 中使用 Perl 對象,同樣需要使用 Perl() 這個構造函數,但與前面的方法不同的是,需要傳遞參數給該構造函數。語法如下:


清單 5. 嵌入式的 Perl 解釋器對象
new Perl($perl_class_name[, $constructor = "new"[perl_para,…]])  

其中第一參數是 Perl 的類(包)名,第二個參數是構造函數的名字(可選)。如果有其他參數,這些參數將被傳遞給 Perl 的構造器。如果第二個參數被省略,默認的構造函數 new() 將被調用。

在 PHP 的腳本中初始化一個 Perl 對象之後便可以跟使用 PHP 自身的對象一樣進行使用,唯一的不同點是方法調用的上下文不一樣,在默認情況下,方法是在標量 scalar 上下文中被調用。要想在 array 或者 hash 上下文中進行調用,可以參照前面的方法:不直接通過 Perl 對象調用該方法,而應該通過一個具體的屬性 array 或者 hash 進行調用。此外初始化 Perl 對象之後還可以在對象之間進行複製操作。


清單 6. 對象操作示例
<?php        $x = new Perl("Test");        $y = new Perl("Test","Test",$x);        $z = clone $y;        echo $z->property;        echo $z->method(1,2,3); // call method "f" in void context        var_dump($x->method(1,2,3));        // call method in scalar context        var_dump($x->array->method(1,2,3)); // call method  in array context        var_dump($x->hash->method(1,2,3));  // call method in hash context  ?>  

在上面的實例代碼中 Test 是一個 Perl 類,在 PHP 代碼環境中可以用 require() 的方法將其包文件從外部引入也可以在 PHP 腳本中利用 Perl 對象的 eval 函數直接構造這樣一個 Perl 類,實例的第一行將調用 Test 類中的 new 方法構造 Test 對象,而第二行將調用 Test 類中的 Test 方法構造 Test 對象。





統一的數據訪問介面PDO

PDO(PHP Data Objects) 擴展為 PHP 訪問資料庫定義了一個輕量級的、一致性的介面,它提供了一個數據訪問抽象層,這樣,無論使用什麼資料庫,用戶都可以通過統一的函數執行來查詢和獲取數據。注意,你並不能使用 PDO 擴展本身執行任何資料庫操作,必須使用一個 database-specific PDO driver (針對特定資料庫的 PDO 驅動)訪問資料庫伺服器。

目前 PDO 支持如表1中資料庫操作介面:


表 1. 支持 PDO 的驅動及相應的資料庫列表
驅動程序名 所支持的資料庫伺服器
PDO_DBLIB FreeTDS / Microsoft SQL Server / Sybase
PDO_FIREBIRD Firebird/Interbase 6
PDO_IBM IBM DB2
PDO_INFORMIX IBM Informix Dynamic Server
PDO_MYSQL MySQL 3.x/4.x/5.x
PDO_OCI Oracle Call Interface
PDO_ODBC ODBC v3 (IBM DB2, unixODBC and win32 ODBC)
PDO_PGSQL PostgreSQL
PDO_SQLITE SQLite 3 and SQLite 2

PDO 並不提供資料庫抽象,它並不會重寫 SQL 或提供資料庫本身缺失的功能,如果用戶需要這種功能,就必須使用一個更加成熟的抽象層。PDO 是隨 PHP 5.1 發行,在PHP 5.0的 PECL 擴展中也可以使用。PDO 需要 PHP 5 核心面向對象特性的支持,所以它無法運行於之前的PHP 版本。

PDO 的安裝部署方法將會在後面的章節介紹,此處先介紹 PDO 的使用。

連接和連接管理

資料庫連接的建立可以通過創建一個 PDO 基類的實體實現,開發人員不用關心需要使用的是那個驅動,在代碼中只需要使用 PDO 的類名。構造函數接受一個參數來表明數據源(也就是通常所知的 DSN)。另外還有三個參數是可選的,如果資料庫伺服器的連接需要提供用戶名和密碼,則需要在構造函數中指定;在該構造函數中,同時還可以通過第三個可選參數傳遞連接類型等的信息。


清單 7. 建立 PDO 連接(以 DB2 Server為例)
<?php      function Connect()      {          try{              $dbh = new PDO(‘odbc:test’,‘user’,‘password’,                  array(PDO_ATTR_PERSISTENT =) true));          } catch(PDOException $e) {              echo 'Connection failed: ' . $e->getMessage();              die();          }          return $dbh;      }  ?>  

odbc:test 告訴 PDO 它所應該使用的 ODBC 驅動程序,並且應該使用 "test" 資料庫。如果使用一個驅動程序管理器,那麼可以用一個 ODBC 級數據源名稱替代 "test"。在冒號字元之後可以指定任何有效的 ODBC 數據源連接字元串。接下來分別是用來連接資料庫的用戶名和密碼。通過設定 PDO_ATTR_PERSISTENT 的值為 true 可以建立一個到資料庫的持久連接,默認情況下不指定此參數建立的連接在腳本運行完畢或者所有對該 $dbh 的應用都被是釋放的時候連接就會被斷開。在某些情況應用程序的設計者只希望建立一次連接,以後對該資料庫所有的訪問操作都通過該連接實現。這時候就可以建立持久連接,持久連接建立後會被緩存並且在其他的資料庫操作腳本訪問該數據源的時候被重用。

斷開連接

默認情況下,當建立的連接是非持久連接時候,當腳本結束時候連接將會斷開,也可以通過顯性的將 $dbh 變數設置為 null 來斷開連接。


清單 8. 斷開 PDO 連接
<?php      function Disconnect($dbh)      {          $dbh = null;      }  ?>  

執行資料庫操作

建立了與資料庫的連接之後就可以對資料庫進行 SQL 查詢操作,對於無返回結果集的資料庫操作(例如刪除,更新,插入等) PDO 通過一個統一的函數 exec() 來實現,這個函數的返回值通常是資料庫操作影響的行數,以刪除為例,函數的返回結果是刪除的行數。而對於需要返回數據結果集的查詢操作則通過 query() 函數來實現。它將返回一個 PDOStatement 類型的結果集合。對於 PDOStatement 類型的結果集可以用它的各種操作方法(例如 fetch() 等)來操作結果集裡面的數據。


清單 9. 執行資料庫操作
<?php  //issues a SQL statement and returns the number of affected rows.  function Execute($execStr)  {      try{          $dbh = Connect();//引用清單1中的方法          $result = $dbh->exec($execStr);      } catch (Exception $e) {              }      return $result;  }  //issues a SQL statement and returns a result set.  function Query($queryStr)  {      try{          $dbh = Connect();//引用清單1中的方法          $result = $dbh->query($queryStr);      } catch (Exception $e) {      }      return $result;  }  ?>  

事務和自動提交

PDO 的事務操作以自動提交模式運行,也就是說如果資料庫支持事務,那麼所運行的每一個查詢都有它自己的隱式事務,如果資料庫不支持事務,每個查詢就沒有這樣的事務。如果需要啟動一個事務操作,必須使用 PDO::beginTransaction() 方法來啟動。這裡需要注意的是:如果底層驅動程序不支持事務,那麼將拋出一個 PDOException。在一個事務中,可以使用 PDO::commit() 或 PDO::rollBack() 來結束該事務,這取決於事務中運行的代碼是否成功。


清單 10. 運用事務操作進行批處理
<?php      //issues a set of SQL statement during a transaction      function Execute (array $tranStr)      {          try{              $dbh = Connect();//引用清單1中的方法              $dbh->beginTransaction();              foreach($transStr as $stateStr)              {                  $dbh->exec($stateStr);              }              $dbh->commit()          } catch (Exception $e) {              $dbh->rollBack();          }          return $result;      }  ?>  

在上面的函數中所要執行的一系列 SQL 命令包括在 beginTransaction() 和 commit() 調用中,可以保證在更改完成之前,其他人無法看到更改。如果發生了錯誤,catch 塊可以回滾事務開始以後發生的所有更改。這樣可以有效的保證數據的一致性,在需要同步進行操作的數據更新中有重要應用。當腳本結束或當一個連接即將被關閉時,如果有一個未完成的事務,那麼 PDO 將自動回滾該事務。

預處理語句

首先需要解釋一下預處理語句,通常將預處理語句看作要運行的 SQL 的一種編譯過的模板,它可以使用變數參數進行定製。以運行一個重複插入數據為例,當往一個表中反覆插入不同的數據的時候,使用預處理語句只需要編譯一次,每次插入的時候只需要將變數用具體的參數取代即可。這可以在很大程度上提高資料庫的性能。大部分成熟的資料庫都支持預處理語句,即使驅動程序不支持預處理語句,PDO 也將模擬預處理語句。


清單 11. 使用預處理語句
<?php      $dbh = Connect();      $prepareStatement = $dbh->prepare(“INSERT INTO STUDENT (id,name) VALUES (:id,:name)”);            //bind the placeholder with a specify variable.      $prepareStatemnet->bindParam(‘:id’, $id);      $prepareStatement->bindParam(‘:name’, $name);            //insert records.      $id = ‘1’;      $name = ‘user1;      $prepareStatement->execute();      $id = ‘2’;      $name = ‘user2;      $prepareStatement->execute();  ?>  





示常式序:一個簡單的網路連通性測試工具

在這個簡單的示常式序中,使用 Perl 編寫一個檢查指定的伺服器是否可以通過操作系統 ping 命令測試網路連通的函數,並通過 PHP 調用該方法獲取測試結果,同時將測試的結果存入基於 DB2 的資料庫中。在這個基於 WEB 的示常式序中,對於測試伺服器網路是否可連接的 Perl 語言代碼在附件的實例代碼中,讀者可以下載閱讀。本文將不對該部分代碼做解釋,而將主要的精力放在描述 PHP 調用 Perl 代碼的方法和 PDO 操作資料庫的方法上。讀者可以在本文的代碼下載中獲取到完整的該程序的源代碼。

開發環境的搭建

本演示常式由數個樣本程序組成,並使用了下列組件及開發測試工具:

操作系統:RedHat Enterprise Linux Server 5.0

  • WEB 伺服器:Apache 2.2.8
  • 資料庫伺服器:DB2 Server Enterprise Edition 9
  • PHP:5.0.0/5.2.6
  • Perl:5.8.0

對於 PHP 和 Apache 的安裝部署在本文中不做重複介紹,以下僅介紹 PDO 和 Perl 擴展的安裝與部署方法。

PHP Perl擴展的安裝與部署

PHP 的 Perl 擴展可以在 PECL 的網站http://pecl.php.net/package/perl獲得下載。為了正確安裝和使用該擴展,操作系統的軟體環境必須滿足以下需求:

  • PHP 5.0.0 RC2 以上版本
  • Perl 5.8.0 以上版本

編譯擴展文件,PHP_PREFIX 和 PERL_PREFIX 必須指向 PHP 和 Perl 的安裝路徑。

#export PHP_PREFIX="/usr"  #export PERL_PREFIX="/usr"  #$PHP_PREFIX/bin/PHPize  #./configure --with-Perl=$PERL_PREFIX --with-PHP-config=$PHP_PREFIX/bin/PHP-config  #make  

安裝(這一步需要根用戶特權)

#make install  

在 php.ini 中添加 Perl 擴展 (這一步需要根用戶特權)

extension=Perl.so  

PDO 擴展的安裝部署

PHP 5.1 發布時附帶了 PDO,但是也可以通過 PECL 這個 PHP 擴展庫來結合使用 PDO 和 (1) PHP 5.0.3 及以上版本的安裝。

在示例應用程序的開發中,所使用的是一個 DB2 資料庫伺服器。需要注意的一點是在安裝PDO 時需要 ODBC 驅動,這就需要在本地安裝有 DB2 管理客戶機,否則編譯將失敗。

在 PHP 5.0.3 及以上版本上通過 PECL 進行安裝

默認情況下,PHP 將安裝 "PEAR" 包管理系統。為了成功地安裝 PDO,需要升級到 PEAR 1.3.5(需要跟用戶特權);使用以下命令

#pear  upgrade PEAR  

接下來就可以安裝 PDO 了(同樣需要根用戶特權):

#pear install PDO

安裝完 PDO 核心后,為了使之生效,需要在 php.ini 文件中添加以下內容:

extension=pdo.so  

接下來需要安裝用於 PDO 的 ODBC 驅動程序

#pear install PDO_ODBC   

按照提示輸入 ODBC 驅動程序的類型和驅動程序的位置,在示常式序中使用的是 DB2 伺服器,如果採用 DB2 的默認安裝選項,可以直接輸入 ibm-db2,如果選擇了不同的安裝位置,就要用實際的位置替換 /home/db2inst1/sqllib。由於 PEAR 不會為用戶配置 PECL 擴展,因此在安裝完成後需要將驅動程序添加到 php.ini 文件中,從而在PHP中正確載入驅動程序。確保將下面的內容添加在之前所添加的 pdo.so 這一行之後,否則 PHP 將不能正確地初始化。

extension=pdo_odbc.so

(2) PHP 5.1及以上版本的安裝

PHP 5.1 發布時附帶了 PDO,為獲得 DB2 支持,只需在編譯 PHP 時將下面的開關添加到配置行。

#tar xzvf php-5.2.6.tar.gz  #cd php-5.2.6  #./configure –with-pdo-odbc=ibm-db2,/home/db2inst1/sqllib --with-apxs2=/usr/sbin/apxs  #make  #make install  

安裝完畢后,應該完全重新啟動 WEB 伺服器,以確保 PHP 裝載新的擴展,這樣就可以開始使用 PDO 了。如果您使用的是 UNIX 平台,那麼需要獲得 DB2 客戶機的 DB2 實例環境,以便正確地初始化,可以通過運行命令 source /home/db2inst1/sqllib/db2profile 來完成。

示常式序

該示常式序的流程和結構如下圖所示,下面將分別介紹各個部分的功能及實現方法。讀者可以在本文附帶的示例代碼中


圖 1. 示常式序總體結構

測試伺服器連通性的 Perl 模塊(Connectivity Test Module)

代碼文件:SERVERCHECK.pm

該模塊採用 Perl 編寫,使用 Perl 的系統調用函數 system() 執行 ping 命令,將標準輸出輸入到日誌文件中,然後利用 Perl 的正則處理能力校驗文件中的內容,從來判斷伺服器的是否能通過 ping 命令檢測遠端伺服器的網路是否連通。在該函數中所調用的validate_cmd_response()函數會調用system()系統函數並捕獲標準輸出,同時驗證標準輸出中是否匹配指定字元串。


清單 12. 判斷遠端伺服器網路連接性
sub server_is_connective {      my( $class) = shift @_;      my( $serverIp ) = @_;      my( $pingOption,$validValue);      $pingOption = '-c 2';      $validValue = ("2 packets transmitted, 2 received, 0% packet loss");      my($rtnValue) = &validate_cmd_response("ping $pingOption $serverIp",$validValue);      print $rtnValue;  }    sub validate_cmd_response{      my( $cmd,$pValid) = @_;      if( $cmd ){          my ( @stdoutValue ) = &x_execute_cmd( $cmd );              if ( grep( /$pValid/i, @stdoutValue ) ){              return 1;          }      }      return 0;  }  

PHP-Perl函數連接器(PHP-Perl Connector)

代碼文件:Connector.php

該部分實現一個是從 Perl 介面向 PHP 介面轉化的連接方法,在該部分中將 Perl 類中的方法轉化成PHP函數。


清單 13. PHP 調用 Perl
<?php      public function php2perl($func_name,array $para_array)      {          $func_str = $func_name."(\"\",";          $conn_str = "";          foreach($para_array as $para)          {//add all parameters              $func_str.= $conn_str."\"".$para."\"";              $conn_str = ",";          }          $func_str .= ");";          try {              ob_start();              $perl = new Perl();              //push the complete directory of perl file into @INC variable              $perl->eval('push(@INC,"/web/www.domain.com/docs/sample");');              $perl->eval('use SERVERCHECK');              $result = $perl->eval("SERVERCHECK::$func_str");              $out = ob_get_contents();              ob_end_clean();          } catch(PerlException $excep){              echo "Perl error".$excep->getMessage()."\n";              $out = "Perl error";          }          return $out;      }  ?>  

在實例代碼中只給出了一個轉換,如果 Perl 代碼中有其他的介面,也可以按照相同的方式將其轉化為 PHP 介面。只要在方法中給出要調用的 Perl 方法的名字,並將要傳遞的參數放到一個數組中作為第二個參數,然後調用 php2perl() 方法就可以實現。在所定義的 PHP 函數 is_server_connective() 中,通過直接調用 php2perl() 函數,可以直接獲得 Perl 函數 server_is_connective() 的返回結果。


清單 14. 使用php2perl的方法將Perl函數加以封裝
public function is_server_connective($server)  {      $para = array($server);      $result = $this->php2perl('server_is_connective',$para);      return $result;  }  

資料庫操作模塊(DB Operation Module)

代碼文件:

PdoOpt.php(PDO 通用操作類)

GeneralDbOpt.php(資料庫通用操作類)

ServerData.php(serversample 表操作類)

該模塊實現應用程序跟 DB2 伺服器的通信,通過這個部分可以將資料庫中需要測試網路連接的伺服器信息(主機名和地址)查詢出來,在完成伺服器連通性測試之後將測試結果更新回資料庫中。在這裡將 PDO 的基本操作單獨抽象為一個類 PdoOpt,當需要更換資料庫的時候可以在該文件中更改相應的資料庫驅動等信息即可。基於此類可以建立出對資料庫數據進行增刪改查等基本的操作的資料庫通用操作類 GeneralDbOpt,下面的代碼演示了該類使用 PdoOpt 類執行數據查詢的方法。


清單 15. 通過 PdoOpt 從指定表中查找指定id的數據結果
public function select($table,$select_id)  {     $sel_str = "select *  from $table ";     if($select_id !== ""&& $select_id !== null)      {         $sel_str .= " where id =".$select_id;     }     try{         if($result = $this->pdoOpt->Query($sel_str))         {             $rtn_value = $result->fetch(PDO::FETCH_ASSOC);         }     } catch(Exception $e) {         echo $e->getMessage();     }     return $rtn_value;  }  

在此類基礎之上構建對於具體表的操作方法。應用中以操作 serversample 表為例實現了一個 ServerData 類。所有對該表的操作都在該類中實現。以獲取資料庫中所有的伺服器信息為例演示如何使用 GeneralDbOpt 類


清單 16. 從資料庫中獲取伺服器列表
public function get_server_list()  {      $fields = array('id','name');      $tables = array ($this->table);      return $this->general_db_opt->select_all($tables,$fields,'');  }  

資料庫說明:資料庫表中只有一個簡單的演示用表 serversample,該表中有 id,name,ip,status 四個欄位,分別代表伺服器的標識,主機名,IP地址和狀態信息。具體信息可以參看附件中的資料庫表結構信息。

頁面展現模塊(Web View)

為了更好更清晰的展現該示例應用程序的邏輯結構,在該部分簡單採用了 Smarty 的模板技術,避免將PHP 代碼夾雜到 HTML 代碼中。只使用該技術將資料庫中查出的伺服器信息呈現到頁面上,在 Smarty 的網站 http://smarty.php.net/ 可以下載安裝該引擎。


清單 17. Smarty 簡單示例
<?php      require('/usr/local/lib/php/Smarty/Smarty.class.php');      define('_SMARTY_ROOT','/web/www.domain.com/Smarty');        $smarty = new Smarty();      $smarty->template_dir = _SMARTY_ROOT."/templates";      $smarty->compile_dir = _SMARTY_ROOT."/templates_c";      $smarty->cache_dir = _SMARTY_ROOT."/cache";      $smarty->config_dir = _SMARTY_ROOT."/configs";      $smarty->right_delimiter = '}>';      $smarty->left_delimiter = '<{';  ?>  

應用程序邏輯

首先獲取伺服器的信息並顯示到頁面上,可以通過 get_server_list() 方法獲取到伺服器的信息,然後將其賦值給 server_info 變數,Smarty 在頁面上控制如何展現這些伺服器信息。


清單 18. 從資料庫中獲取所有伺服器的信息並在 WEB 頁面呈現
<?php      require('main.php');      require('ServerData.php');      $serverData = new ServerData();      $server_info = $serverData->get_server_list();      $smarty->assign('server_info',$server_info);      $smarty->display('serverping.tpl');  ?>  

當點擊頁面上的 Test 按鈕時候會獲取當前按鈕所指定的伺服器的 id,從而獲得所需要測試連通性的伺服器信息,通過調用 connector 的方法測試,測試完畢后調用 ServerData 的更新方法將測試結果更新進資料庫中指定 id 的伺服器信息中。


清單 19. 從 PHP 端測試伺服器連通性並將數據更新至資料庫中
___FCKpd___24

當點擊了每行右側的 Test 按鈕后,可以獲得所測試的伺服器 IP 地址的網路連接是否成功:


圖 2. 示常式序





結束語

至此,本文已經介紹了基於 PHP 5 面向對象特性的兩個 PECL 擴展的安裝部署及使用方法,同時通過示例演示程序,基本介紹了這兩個 PECL 擴展的具體應用方法。基於 PHP 5 面向對象新特性的諸多 PECL 擴展給 PHP 開發帶來極大的便捷,也大大增強了 PHP 的語言擴展功能。如果您想在其他的環境下部署您的應用程序或者獲得這兩個基於 PECL 的擴展更為詳細的信息,可以通過訪問 PHP 和 PECL 的網站來獲得這兩個擴展的詳細手冊與說明。(責任編輯:A6)

GET["serverid"]; $serverData = new ServerData(); $serverData->get_server_info($server_id); //get server ip information $server_ip = $serverData->ip; $connector = new Connector(); $result = $connector->is_server_connective($server_ip); //test server connectivity if($result) { //print test result and update server information } else { //print test result and update server information } $serverData->update_server_info($server_id);//update test result into database echo $rtn_str; ?>

當點擊了每行右側的 Test 按鈕后,可以獲得所測試的伺服器 IP 地址的網路連接是否成功:


圖 2. 示常式序





結束語

至此,本文已經介紹了基於 PHP 5 面向對象特性的兩個 PECL 擴展的安裝部署及使用方法,同時通過示例演示程序,基本介紹了這兩個 PECL 擴展的具體應用方法。基於 PHP 5 面向對象新特性的諸多 PECL 擴展給 PHP 開發帶來極大的便捷,也大大增強了 PHP 的語言擴展功能。如果您想在其他的環境下部署您的應用程序或者獲得這兩個基於 PECL 的擴展更為詳細的信息,可以通過訪問 PHP 和 PECL 的網站來獲得這兩個擴展的詳細手冊與說明。(責任編輯:A6)



[火星人 ] 基於 PHP5 面向對象特性的 PECL 擴展 Perl 與 PDO 編程已經有842次圍觀

http://coctec.com/docs/linux/show-post-68986.html