天天看點

使用 CodeIgniter 架構快速開發 PHP 應用(四)

使用 CI 簡化資料庫開發

你學習CI 是因為你想要使程式設計更容易和更有生産力。這一章講述CI的Active Record類。 如果CI隻提供一個Active Record類,它還是物超所值的。當然,CI是免費的,隻不過我要強調Active Record(以後簡稱AR)類的價值是非常高的,它是你提高生産力的主要工具。

AR使你以最小的代價獲得最大的回報。 它簡單,易于使用和維護。

這一章描述CI如何連接配接到一個資料庫,你如何使用AR操縱資料庫。你将會見到:

。 AR類與傳統PHP/MySQL接口的比較

。 如何讀取資料庫并顯示結果

。 如何建立,更新, 删除查詢

CI保留讓你用傳統的方法編寫資料庫查詢,但是我不會詳細介紹這部分内容。它的知識完全被線上手冊覆寫。使用AR類後,你可能不會再用傳統的方式來做資料庫查詢了。

配置config檔案

你或許已經注意到在這本書的大多數的章節會談到system/application/config 檔案夾和裡面的config檔案。這些檔案對控制CI按要求工作相當必要。而且你可以讓大部分的配置參數等于系統的預設值。資料庫config檔案在正常使用資料庫之前需要進行設定。

基本上,你僅僅必須告訴它你的資料庫在哪裡、它是什麼類型。 檔案的預設值為:

$active_group="default";

$db['default']['hostname']="";

$db['default']['username']="";

$db['default']['password']="";

$db['default']['database']="";

$db['default']['dbdriver']="";

其他的選項可以保留為預設值。 必選項是:

hostname: 你的資料庫的位置, 舉例來說, 'localhost' 或 IP 位址

username和password: 使用者名稱和密碼必須有充分的權限,允許你的網站存取資料庫中的資料。

database: 你的資料庫的名字, 舉例來說, 'websits'

dbdriver: 你正在使用的資料庫的類型 - CI可受的有選項有MySQL、MySQLi、 Postgre SQL、ODBC和MS SQL

以我的經驗來看, 最困難的事情之一就是把新的CI網站連接配接到資料庫。你可能需要查詢你的ISP-有時他們的資料庫運作在與他們的web server IP位址不同的地方。如果你正在使用 MySQL, 他們可能提供 phpMyAdmin, 通常告訴你 hostname-這可能是 'localhost' 或者它可能是一個 IP 住址。

你可能注意到 config 檔案的内容實際上是一個多元數組。在 $db數組裡包含一個叫做default的數組,你所做的設定就是往裡增加鍵/值對,例如 hostname = 127.0.0.1 。你還可以增加其他的資料庫設定, 通過改變$active_group的設定可以容易地更改資料據庫。

這為網站連接配接到數個資料庫提供了可能性-舉例來說, 一個測試資料庫和一個産品資料庫-你可以很容易地在他們之間切換。 或者你可以在二個資料庫之間交換資料。

為我們的網站設計資料庫

我想表達的是 CI 能用來開發正式的網站。 我現在正在維護客戶的一些網站,而且我想要監控他們,用我設計的方法測試它們, 用資料庫儲存我想要的資料, 而且可以得到這些網站的分析報告。 是以讓我們試着建立它。 先讓我們确定一些目标。 它們是:

1. 用最少的人工幹預管理一個或更多的遠端網站

2. 對遠端網站進行定期的測試

3. 生成符合要求的分析報告, 提供網站的細節和測試結果

是以, 第一件事情是我們将會需要一個網站的資料庫。 建立一個名為websites的MySQL資料庫,你也可以使用别的資料庫産品。

現在,我們需要增加一些表來儲存各種資料。讓我們為網站增加一張表,字段有URL,他們的名字和密碼/使用者名, 和他們的類型。我們也将會為每個網站建立一個ID字段-而且在 MySQL資料庫中,至少,需要為實體生成一個唯一辨別符,可以使用自動增量類型來達到這一目的。

每個網站必須有一個不同的主機,我們需要另一表來儲存主機資訊。一般有一個域名與主機相關聯,是以我們需要一個域名表來儲存有關域名的資訊,還需要一個人員表來記錄這些人的姓名,密碼,郵件位址,備用郵件位址,手機号碼,曾至寵物的名字,可能還有其它的一些什麼。

是以我們的網站表需要包括這樣一些字段:domain ID, host ID, 兩個people ID,一個存放網站站長的ID一個存放網站管理人的ID(管理人為網站提供技術支援,保證網站正常運作.)

你能見到,這是一個完整的關系型資料庫,讓我們來建立它!

完整的建表文檔,SQL檔案格式:

websites.sql:

SQL

複制代碼

我們現在要用一個更簡單容易的方法來實作這一切。 是以,讓我們看看CI架構為我們提供了什麼功能,我們要重點介紹AR類。

Active Record

AR是一個'設計模式'-又一個高度抽象的東西,就象 MVC。 它本身不是代碼, 隻是一個模式。對于代碼。 有一些不同的解釋。它的核心是把你的資料庫和PHP對象建立一個對應關系。每次,當你執行一個QUERY語句。每一張資料庫裡的表是一個類,每一行是一個對象。所有你需要做的隻是建立它,修改它或者删除它。例如,“方法”,是從類繼承而來。Ruby on Rails 是使用AR模式的,CI也是,盡管這兩種架構實作AR的方式有一點不同。

理論的東西夠多了-但是這是什麼意思呢?好吧, 用代碼簡單和清楚地描述一下吧。

使用AR類的優點

AR節約你的時間,自動運作,使SQL語句友善易懂。

節約時間

當你在PHP程式設計時,每寫一個資料庫查詢的時候,你每次一定要與資料庫建立連接配接。 對CI來說,第一次連接配接資料庫時,你在每個控制器或模型的構造函數裡放入這樣一行語名:

$this->load->database();

一旦你這樣做了,你不需要重複連接配接, 在那個控制器或模型就可以做任意多次的查詢。

你已經在 config檔案中設定了關于資料庫的參數,就象我們在這一章開始時看到的一樣。 再一次,這使更新你的網站比較容易,如果你想要改變資料庫名字、密碼或位置的話。

自動機制

一經你已經連接配接到資料庫, CI 的AR生成隐含的代碼。 舉例來說, 如果你進行下列的插入操作:

PHP

              'title'=> $title,

              'name' => $name,

              'date' => $date

              );

$this->db->insert('mytable',$data);

你正在插入的資料據已經被在幕後轉換成這樣一行代碼:

function escapte($str) {

   case 'string':

     $str="'".$this->escape_str($str)."'";

     break;

   case 'boolean':

     $str=?($str=== FALSE) 0: 1;

   default  :   

     $str=?($str=== NULL) 'NULL': $str;

   }            

return $str;

}

換句話說, CI架構使你的代碼變得更強健。 現在,讓我們看看它是如何工作的。

第一,連接配接資料庫非常簡單。 在傳統的PHP程式設計時,你可能是這樣做的:

      foreach($row as $attribute) {

         print "{$attribute[1]}";

      }

  }

換句話說,你必須重複地輸入host、username和password,建立一個連接配接,然後選擇一個連接配接的資料庫。 你必須每次都這樣做,然後再開始一個查詢。 CI以一條指令替換連接配接工作:

在每個控制器或者模型中或者其它類的構造函數裡放入這條指令。 在這之後,你就可以直接開始查詢了。 連接配接資料被儲存在你的資料庫 config 檔案中,CI每次都會去那裡查詢它。

是以, 在每個CI函數中,你可以直接進行資料庫查詢。上面的query在CI中被轉換成:

$query = $this->db->get('sites');

   foreach($query->result() as $row) {

      print $row->url

   }

很簡單, 不是嗎?

這一個章的餘下部分給出不同query的用法。

讀取查詢

常用的查詢是取回來自資料庫的資料。等同于select的查詢是:

$query =$this->db->get('sites');

這是一個'select *' 查詢,目标是site表-換句話說,它取回所有的行。 如果你偏愛分開來寫,你能這樣做:

$this->db->from('sites');

$query = $this->db->get();

如果你想要得到特定的列, 而不是全部列, 這樣做:

$this->db->select('url','name','clientid');

你可能要對結果排序,你可以在get語句前插入:

$this->db->orderby("name","desc");

desc是降序的意思。 你也能選擇asc(升序) 或

rand(random).

你也可能想要限制傳回的行數,比如你想要最初五個結果。你可以在get語句前插入:

$this->db->limit(5);

當然,在大多數的查詢,你不可能在表中傳回所有記錄。 資料庫的具有按給定條件過濾傳回結果的能力。 這通常使用where子句來實作, CI 這樣表達:

$this->db->where('clientid','1');

這條語句會查找客戶号是 1 的客戶相連的所有的網站。 但是這對我們并不是很有幫助,我們并不會記住人員表的ID号。對人來說,用姓名是比較合理的辦法,是以我們需要連接配接到people表: 

$this->db->join('people','sites.peopleid=people.id');

有SQL知識的人都知道,這相當于:

注意 SQL 的約定,如果一個列名在二張表中是重複的, 你需要在列名前加上表名和一個“."号。 是以 sites.peopleid 在位置桌子中意謂 peopleid 所在的表是sites.在進行SQL多表查詢時,最好把列名進行唯一性的辨別,這樣可以避免産生岐義,也可以讓你自己明了。

你可以增加更多的where子句的操作符。 舉例來說,增加否定操作符:

或比較操作符:

$this->db->where('id >','3');

或聯合陳述: ("where ...and..."):

或使用 $this->db->orwhere()來表示: ("where …or "):

現在讓我們建立一個完整的查詢:

$this->db->select('url','name','clientid','people.surname as client');

$this->db->where('clientid','3');

$this->db->join('people','sites.clientid=people.id');

$this->db->orderby("name"," desc");

這應該給我們前五個 (用姓名排序)網站,這些網站屬于 3 号客戶, 而且還顯示客戶的姓和他或她的身份證數字!

使用AR的潛在好處是已經進行了自動的轉義,是以,你不必關心轉義的問題。 這适用于這樣的函數象$this->db->where(), 以及在下一個段中被描述的資料插入和修改語句。(安全警告: 這不同于阻止交叉腳本攻擊-對付這個你需要 CI 的 xss_clean() 函數。它也不相同于驗證你的資料-對付這個你需要 CI 的驗證類。 見第 5 章。)

顯示查詢結果

在CI顯示查詢結果相當簡單。假定我們定義了上述的查詢語句, 最後一句是:

$query =$this->db->get();

然後,如果有多個結果,他們被儲存在$row對象中,你可以用一個 foreach 循環:

foreach($query->result() as $row) {

    print $row->url;

    print $row->name;

    print $row->client;

或如果我們隻想要一個結果,它可以作為一個對象被傳回, 或在這裡當做一個

$row數組:

if ($query->num_rows()>0) {

   $row =$query->row_array();

   print $row['url'];

   print $row['name'];

   print $row['client'];

我比較喜歡對象文法勝過數組-更簡潔!

如果你遵守 MVC 模式,你将會在模型中儲存你的查詢和資料庫互動, 然後通過視圖顯示資料。

生成和更新查詢

AR有三個函數幫助你在資料庫内生成新的實體,它們是$this->db->insert(),$this->db->update,$this->db->set().

“create"和“update"的不同之處是“create"是向表中插入一條全新的記錄,而"update"是修改表中已經存在的記錄。是以對“update",你必須首先定位需要修改的記錄。

CI 用數組來儲存資料,或是使用$this->db->set(); 你可以任選一種。

是以, 如果要在websites資料庫中加入一行。首先,確定在我們的控制器中的構造函數加入:

我們想要增加一個新的網站,包含有一個網址,一個名字,一個類型和一個客戶ID。 如果用數組的方式,這可能是:

               'url'       => 'www.mynewclient.com',

               'name'      => 'BigCo Inc',

               'clientid'  => '33',

               'type'      => 'dynamic'

把這些資訊增加到sites表,我們使用:

$this->db->insert('sites', $data);

我們更可以使用$this->db->set():

$this->db->set('url','www.mynewclinet.com');

$this->db->set('name','BigCo Inc');

$this->db->set('clientid', '33');

$this->db->set('type','dynamic');

$this->db->insert('sites');

如果我們正在更新一筆現有的記錄, 我們也可以建立一個數組, 或使用 $this->db->set(), 但是現在有二個不同。

第一, 我們必須定位我們想要更新的記錄; 其次,我們需要使用$this->db->update(). 如果我想要在sites中更新一筆記錄(針對'id'列的值1的那行記錄),使用數組的方式是這樣處理的:

$this->db->where('id','1');

$this->db->update('sites', $data);

你也可以使用$this->db->set()方式, 就象前面做過的那樣。

CI 提供幾個函數檢查資料庫是否成功執行了相關操作。 最有用的:

$this->db->affected_rows();

在執行insert或update後應該傳回 '1'-但是如果我正在update一批記錄的話,可能傳回更大的一個整數。

你已經注意到當我insert一筆新的記錄時,我沒有設定ID這一列。這是因為ID這列被設定為自動插入類型。但是當我update一筆現有的記錄時候,我必須引用ID屬性,否則資料庫不知道該改變哪一筆記錄。

如果我正在insert一筆新的記錄, 在實際産生它之前,我們并不知道ID具體的值。如果我需要引用新的記錄的ID, 使用下列語句:

$new_id_number = $this->db->insert_id();

(這一行代碼必須跟在insert語句之後,否則可能得到錯誤的結果.)

還有一點需要知道,CI的AR操作, 包括 $this->db->insert() 和 $this->db->update()會被自己地轉義。

從 1.5 版, CI 也包含了對事務的支援,即指定的一批SQL操作要麼全成功,要麼全失敗,換句話說,要麼送出,要麼復原。這在複式記帳應用和許多商業應用中是很重要的。舉例來說,說你正在賣電影票。 你需要接受付款, 同時配置設定座位。 如果你的系統收費成功但配置設定座位失敗,這個客戶肯定是要光火的。

CI 現在也讓事務處理變得很簡單,即要麼“送出”,要麼復原。你可以參考使用者手冊以得到更多關于事務的資訊。

删除操作

删除操作也許是最簡單的。你隻要定位好需要删除記錄,比如我們要删除ID為2的記錄:

$this->db->where('id','2');

$this->db->delete('sites');

要小心使用删除操作,因為如果你不注意where中的條件,可能會誤操作,甚至最壞的結果是删除整張表。

AR和傳統SQL程式設計的結合

CI 不要求你隻能使用AR,你也能用CI直接發送SQL查詢。比如:假定你已在構造函數裡已連接配接了資料庫,你可以在需要的地方直接使用類似的SQL查詢:

$this->db->query("select id, name, url from sites where 'type'='dynamic'");

我個人覺得AR更容易使用。借助數組為AR準備資料更直覺,更容易了解,雖然可能需要更多的代碼。AR還能自動轉義,對不熟悉SQL文法的程式員會更有吸引力。

還有需要介紹的一個使用AR的技巧是關于where函數的,當我們需要在where中放入這樣一個比較複要的語句時:

  client='3' and (type = 'dynamic' or type = 'static')

由于使用了左右括号,是以不能直接放入where函數,你可以把這分成兩行:

  $c;

  $this->db->where($condition);

在一些複雜的情況下,你可能需要直接使用SQL文法建立查詢而不是使用AR,比如要使用複雜的表連接配接,子查詢,左連接配接等等。不管怎樣,CI架構確定你能做到傳統PHP能做到的一切,而帶來更多的好處。

需要指出的是,如果你試着混合使用AR和直接的SQL查詢,你可能會有麻煩。

摘要

我們已經介紹了CI的Active Record類,而且見到,它是多麼容易使用:

。建立和一或較多的資料庫的連接配接

。使用AR從資料庫讀取資料或插入,更新,删除資訊

。或直接使用SQL的标準文法執行查詢

CI 的AR功能是概念清晰又容易使用, 而且使代碼非常易讀。它自動化資料庫連接配接,并把連接配接資料儲存至一個 config 檔案。