韌館-LearnHouse

Archive for 11 月 16th, 2007

[PHP]物件導向程式設計

資料來源:http://php.igt.com.tw/unit_111.htm

PHP 支援物件導向程式設計,雖然就純粹的物件導向程式設計的觀點來看,它的支援並不是很完整,但是,只要我們遵循良好的程式設計習慣,我們還是可以善用 PHP ,來開發物件導向的程式。

為什麼要使用物件導向的程式設計?

在 物件導向程式設計的觀念提出之前,軟體開發者,大多是使用結構化的程式設計。所謂結構化的程式設計,就是把問題切割成各個比較小的問題,比較小的問題,如 果還是複雜到無法以一個函式來解決時,就在切割成為更小的問題。直到可以用一個單一的函式來解決為止。每個函式處理個別的功能,主程式藉由呼叫各個函式, 來完成他的工作。

課程111:物件導向程式設計
摘要:


在這個課程中,我們將討論物件導向程式設計。首先,我們討論物件導向程式設計的觀念。接著,我們以實例來示範 PHP 物件導向程式設計的撰寫。然後,再把物件導向程式設計的方法,應用在留言版的程式中。

物件導向程式設計觀念


PHP 支援物件導向程式設計,雖然就純粹的物件導向程式設計的觀點來看,它的支援並不是很完整,但是,只要我們遵循良好的程式設計習慣,我們還是可以善用 PHP ,來開發物件導向的程式。

為什麼要使用物件導向的程式設計?

在 物件導向程式設計的觀念提出之前,軟體開發者,大多是使用結構化的程式設計。所謂結構化的程式設計,就是把問題切割成各個比較小的問題,比較小的問題,如 果還是複雜到無法以一個函式來解決時,就在切割成為更小的問題。直到可以用一個單一的函式來解決為止。每個函式處理個別的功能,主程式藉由呼叫各個函式, 來完成他的工作。

在前一個課程函式的應用, 我們應用了結構化的程式設計,將留言版的功能分割成各個函式,各網頁藉由呼叫各函式的方式,完成存取留言版資料的工作。使用結構化的程式設計,的確簡化了 我們撰寫程式的工作,也提高了程式的可維護性。但是,結構化程式設計在開發大型專案時,還是無可避免的碰到了他的瓶頸。因為,結構化的程式設計,專注於功 能面(函式)的開發,而往往忽略了功能所要處理的資料。被處理的資料與功能在結構化的程式設計是分離的關係。在大型專案的開發上,由於要處理的問題,相對 的要複雜許多,如果,資料與函式之間沒有關聯性,很容易發生錯誤,維護起來也很不方便。後來,物件導向程式設計的興起,就是為了解決,結構化程式設計所面 臨的資料與功能分離的問題。

物件導向程式設計的常用名詞:

  1. 屬性(Property):即物件裡的資料(變數)。
  2. 方法(Method):即物件裡的功能(函式)。
  3. 成員(Member):即類別裡所定義的變數或函式。
  4. 物件:類別的實例。
  5. 類別:物件的定義。由使用者所定義的資料型態。

物件導向程式設計的支柱

物件導向程式設計的三大支柱,稱之為 PIE(Polymorphism多變, Inheritance繼承, Encapulation封裝)。由於,PHP目前的版本只支援繼承及封裝,所以,我們在此,僅討論繼承與封裝。

所 謂封裝,就是把功能與資料包裝起來成為一個物件,並定義物件的介面。讓外界的程式,透過物件所提供的介面,來與這個物件溝通。外界的使用者,無須知道,物 件內部如何執行他的作業。只需要知道,如何使用物件的介面,來完成自己的工作即可。所以,設計物件的開發者,日後要更新物件的程式時,只要維持物件的介面 不變,便可以確保,使用這物件的外部程式,不需要改寫,一樣可以執行。而外界程式的開發者,只要遵循不直接存取物件內部的功能及資料,僅透過介面來使用物 件的規則,便可以確保程式執行無誤。

所謂繼承,就是子類別藉由繼承父類別的方式,取得父類別所定義的屬性及方法。通常,父類別會定義通用的屬性及方法,而子類別則延伸父類別定義特定的屬性及方法,以解決特定的問題。

如何使用物件導向程式設計來開發程式

使 用物件導向的方式來開發程式,最主要的關鍵,在於程式設計觀念的改變。之前,我們使用函式來開發留言版的時候,我們著重在於找出留言版應該具有的功能,然 後,按照功能來撰寫對應的函式。外界的網頁程式,把資料餵給這些功能,來完成它的工作。使用物件導向程式設計時,我們必須把程式所企圖解決的問題,看做是 一個獨立的個體。在這個個體中,包含了它應該處理的資料,以及處理這些資料的功能。這些功能是為了處理這些資料所產生的。所以,在撰寫留言版的程式時,我 們要把留言版當作是一個自給自足的個體。把程式所要解決的問題,定義成為個別的個體,這個過程稱之為抽象化(Abstraction)。

當 我們的腦子裡,有了這個個體所需要的資料以及功能後,我們就可以專注於定義這個個體的類別。把個體的資料,定義成類別的屬性;把個體的功能,定義成類別的 方法。在定義類別時,先別管外界的程式如何運作,全心全力專注於如何按照這個個體的需求,寫好這個類別。類別定義完之後,外界的程式,便可藉由物件變數, 來使用這個我們定義的類別(使用者定義的資料型態)。物件導向程式設計,名稱上雖然是物件,但是,實際上,程式設計師大部分的心力,在於找出問題中的個 體,定義這個個體的類別。使用這類別的程式部分,反而花的時間不多。

在下一節中,我們將使用實際的例子,來實作 PHP的物件導向程式設計。

 


PHP 物件導向程式設計實例演練


說明:

在這一節中,我們使用範例,來學習如何撰寫類別:

  1. 類別的語法結構。
  2. 封裝:定義屬性及方法。
  3. 使用物件:類別的實例化。
  4. 繼承。
一、類別的語法結構

class 類別名稱 [extends][父類別名稱]{

類別的定義

}

說明:

  1. 定義類別時,在 class 保留字之後,是使用者所定義的類別名稱。
  2. 如果,所定義的類別要繼承其他類別時,需加上 extends 保留字,然後,加上父類別的名稱。否則,省略 extends和父類別名稱。
  3. 之後是由 { 和 }所包圍的類別定義。在這裡,類別的定義,包括了屬性及方法。
二、封裝:定義屬性及方法。

class 類別名稱 [extends][父類別名稱]{

// 屬性的定義

var $變數名稱;

// 方法的定義

function 方法名稱([參數列]){

}

}

說明:

  1. 定義類別的個別屬性時,前面必須加 var 保留字。代表這變數是這個類別的屬性。
  2. 定義屬性時,可以給初始值。
  3. 定義方法時,規則同函式。
  4. 在方法中,如果要存取類別的屬性時,必須用 $this->變數名稱 這個格式。變數名稱在這裡,不可以加 $符號。
  5. 如果,類別中的方法名稱與類別名稱相同時,這個方法稱之為這個類別的建構方法。建構方法在類別被實例化時執行。類別實例化,說白一點,就是在外界的程式中,產生這個類別的物件變數。
範例:定義類別
<?php
/* 檔名:111_01.php
定義 Dog 類別
*/

class Dog{
var $food = '骨頭';
var $name;
     function Dog(){
echo '產生 Dog 類別的物件時,便會呼叫這個方法(建構方法)';
}
     function Eat(){
echo $this->name.'吃'.$this->food;
}
}
?>

三、使用物件:類別的實例化。
// 產生物件時
$物件變數名稱 = new 類別名稱;
// 呼叫物件方法或存取屬性時
$物件變數名稱->物件的方法或屬性;

說明:

  1. 要產生物件時,必須以一個變數來存放物件。
  2. 必須使用 new 保留字來產生物件。產生物件時,會執行這個物件的建構方法。
  3. 存取物件的屬性或呼叫物件方法時,物件與其成員之間,必須加 ->
  4. 物件的屬性之前,不可加 $ 符號。
範例:使用物件

程式碼:

<?php
/* 檔名:111_02.php
使用 Dog 類別
*/
// 含括 111_01.php 定義 Dog 類別的PHP檔
include_once('111_01.php');
// 產生 Dog 類別的物件
$mydog = new Dog;
$mydog->name = '來福';
echo '<br>';
$mydog->Eat();
?>
執行程式
四、繼承

說明:

  1. 當子類別繼承父類別時,子類別取得父類別所有的成員(屬性及方法)。
  2. 在子類別的方法,要呼叫父類別的方法時,使用 $this->父類別的方法名稱。
  3. 父類別通常只定義通用的成員。
  4. 子類別延伸父類別原有的功能,可另行定義專屬於子類別的功能。
  5. 當父類別的成員改變時,子類別的成員跟著改變。所以,藉著繼承的關係,可以讓我們的程式維護性大為提高。
範例:繼承

程式碼:

<?php
/* 檔名:111_03.php
定義 Pet, Dog, Cat 類別
*/
class Pet{
var $food;
var $name;
var $language;
     function Pet(){
echo '產生 Pet 類別的物件時,便會呼叫這個方法(建構方法)';
}
     function Eat(){
echo $this->name.'吃'.$this->food;
}
     function Speak(){
echo $this->name.'說'.$this->language;
}
}
class Dog extends Pet{
function Dog(){
$this->food = '骨頭';
$this->language = '汪汪';
echo '產生 Dog 類別的物件時,便會呼叫這個方法(建構方法)';
}
}
class Cat extends Pet{
function Cat(){
$this->food = '魚';
$this->language = '喵喵';
echo '產生 Cat 類別的物件時,便會呼叫這個方法(建構方法)<br>';
$this->Pet();
}
     function showFear(){
echo $this->name.'怕水';
}
}
?>
<?php
/* 檔名:111_04.php
使用 Dog, Cat 類別
*/
// 含括 111_03.php 定義 Pet, Dog, Cat 類別的PHP檔
include_once('111_03.php');
// 產生 Dog 類別的物件
$mydog = new Dog;
$mydog->name = '來福';
echo '<br>';
$mydog->Eat();
echo '<br>';
$mydog->Speak();
echo '<hr>';
$mycat = new Cat;
echo '<br>';
$mycat->Eat();
echo '<br>';
$mycat->Speak();
echo '<br>';
$mycat->showFear();
?>
執行程式

將物件導向程式設計應用在留言版的資料庫網頁


說明:

在這一節當中,我們將把物件導向程式設計,應用在留言版的網頁程式中。

我們按照以下的步驟,來修改留言版的程式:

  1. 準備工作
  2. 產生網站設定檔:web_config.php
  3. 產生資料庫類別檔:db.php
  4. 產生應用程式設定檔:app_config.php
  5. 產生留言版類別檔:Guestbook.php
  6. 修改原本的程式: index.php, add.php, update.php, delete.php
一、準備工作

說明:

將之前110課程所做好的PHP程式,放在另一個新的目錄 guestbook111 之下。然後,在網站的根目錄底下,建立一個 inc 的目錄。存放網站整體各項設定的檔案,以及存取資料庫物件的父類別檔案。

複製檔案:
  1. 使用putty連線到伺服主機。
  2. 輸入以下的命令,進入 public_html 目錄:
    cd public_html
  3. 輸入以下的命令,產生新的目錄 guestbook111,並將 guestbook110 中所有檔案,
    複製到guestbook111:
    cp -r guestbook110 guestbook111
  4. 輸入以下命令,產生新的目錄 inc。用來存放整體網站的設定檔及父類別檔。
    mkdir inc
  5. 輸入以下命令,產生 web_config.php 和 db.php 這兩個檔案。
    touch inc/web_config.php inc/db.php
二、產生網站設定檔:web_config.php

說明:

在 web_config.php 中,我們定義一些有關整體網站各含括目錄所需的參數,以及存取資料庫的設定,方便網站的管理者,日後修改網站的設定。

程式碼:

<?php
/* 檔名:web_config.php
定義各目錄及資料庫參數的常數
*/
// 定義網站目錄的設定
define(WEB_DIR, '/home/lib13/public_html/');
define(INCLUDE_DIR, WEB_DIR.'inc/');
// 定義資料庫的設定
define(DB_HOST, 'localhost');
define(DB_USER, 'lib13');
define(DB_PASSWORD, 'mypassword');
define(DB_DATABASE, 'lib13');
?>
三、產生資料庫類別檔:db.php

說明:

在 db.php 檔案中,我們定義存取資料庫的父類別,供網站中所有需要存取資料庫的類別繼承之用。在這個類別中,我們定義了資料庫連線及選用資料庫的方法 init()。同時,我們也擷取出存取資料庫的通用功能,分別依照功能定義成各種方法。透過繼承這個父類別,其他子類別就可繼承父類別的方法,無須再個別 定義存取資料庫的方法。子類別只需定義,個別類別所需的特定功能。這樣子的做法,一來,減輕修改程式的負擔,提高整個網站程式的維護便利性。二來,要新增 其他類似的資料庫網頁時,可以透過繼承父類別的方式,減少程式碼的撰寫,提高程式開發的效率。

程式碼:

<?php
/* 檔名:db.php
定義資料庫父類別,供其他需要存取資料庫的類別繼承之用。
*/
class DB{
var $add_sql;
var $update_sql;
var $delete_sql;
var $select_sql;
var $retrieve_sql;
     function DB(){
$this->init();
}
     function init(){
mysql_pconnect(DB_HOST, DB_USER, DB_PASSWORD)
|| die('無法與資料庫建立連結');
mysql_select_db(DB_DATABASE)
|| die('無法選擇資料庫:'.DB_DATABASE);
}
     function Add(){
$this->setSQL();
return mysql_query($this->add_sql);
}
     function Update(){
$this->setSQL();
return mysql_query($this->update_sql);
}
     function Delete(){
$this->setSQL();
return mysql_query($this->delete_sql);
}
     function Select(){
$this->setSQL();
return $this->recordset($this->select_sql);
}

function recordset($sql){
$rs = array();
$result = mysql_query($sql);
if($result){
while($record = mysql_fetch_assoc($result)){
array_push($rs, $record);
}
return $rs;
}else{
return false;
}
}
     function Retrieve(){
$this->setSQL();
$result = mysql_query($this->retrieve_sql);
if($result and mysql_num_rows($result) == 1){
return mysql_fetch_assoc($result);
}else{
return false;
}
}
}
?>
四、產生應用程式設定檔:app_config.php

說明:

app_config.php 這個檔案,定義了有關留言版所有網頁程式的設定。其他留言版的網頁,只需含括這個檔案,便可以使用定義好的各種設定。

藉由使用目錄來存放各相關子系統的方式,可以讓我們網站的功能模組化,日後需要增減功能時,只要新增或刪除目錄即可。在各目錄中,放置個別的 app_config.php 檔,來負責個別子系統的環境設定。這樣可以提昇各模組的可攜性,方便網站程式開發的管理。

程式碼:

<?php
/* 檔名:app_config.php
定義這個目錄所需的各項設定
*/
// 含括網站設定檔 web_config.php
include_once('../inc/web_config.php');
?>
五、產生留言版類別檔:Guestbook.php

說明:

Guestbook.php,定義了留言版所需要使用的類別 Guestbook。Guestbook類別藉由繼承父類別 DB,取得了存取資料庫的通用功能。所以,在這個類別,只要定義專屬於留言版的各種屬性及功能即可。

程式碼:

<?php
/* 檔名:Guestbook.php
定義 Guestbook 類別
*/
// 藉由含括子系統的設定檔,取得網站及子系統的各種設定
include_once('app_config.php');
// 含括父類別 db.php 
include_once(INCLUDE_DIR.'db.php');
class Guestbook extends DB{
// 定義屬性
/ 通常可以用所要存取的資料表的各個欄位,作為這個類別的屬性
var $id;
var $name;
var $email;
var $web;
var $content;
var $post_time;
var $fk_icon;
 // 類別的建構方法
function Guestbook(){
$this->DB();
}

// setProperties 方法用來連接表單的欄位以及類別的屬性
function setProperties(){
$this->id = $_POST[id];
$this->name = $_POST[name];
$this->email = $_POST[email];
$this->web = $_POST[web];
$this->content = $_POST[content];
}
 // setSQL 方法定義存取資料表所需的各個 SQL 命令
function setSQL(){
$this->add_sql = 'INSERT INTO Guestbook ";
$this->add_sql .= "(name, email, web, content, post_time) ';
$this->add_sql .= "VALUES('$this->name','$this->email','$this->web',";
$this->add_sql .= "'$this->content',NOW())";
$this->update_sql = "UPDATE Guestbook SET name='$this->name', ";
$this->update_sql .= "email='$this->email', web='$this->web', ";
$this->update_sql .= "content='$this->content' WHERE id=$this->id";
$this->delete_sql = "DELETE FROM Guestbook WHERE id=$this->id";
$this->select_sql = "SELECT * FROM Guestbook ORDER BY post_time DESC";
$this->retrieve_sql = "SELECT * FROM Guestbook WHERE id=$this->id";
}
}
?>
六、修改原本的程式: index.php, add.php, update.php, delete.php

說明:

在這裡,我們含括 Guestbook.php檔案。藉由產生 Guestbook的物件 $obj,按照各網頁程式所需要的功能, 透過 $obj物件,呼叫Guestbook所定義及繼承的各個方法。

index.php
add.php
update.php
delete.php
執行程式
2007年11 月 posted by admin in 程式&軟體 and have No Comments