卓越科技大學校園資訊系統 解題說明
(二)、共用函式
在目前公告的四個題組中,可以見到有不少的資料庫存取動作,一般直覺的寫法就是在有需要撈資料的地方,插入PHP的程式碼區段,然後建立起SQL語句,再用函式送到資料庫去執行得到資料回來,最後依照題目要求把資料echo出來,呈現在網頁上;如果這樣的動作要在一個題組中重覆幾十次,不但沒有效率,而且也容易出錯,因此在解題上,我會建議先建立起資料庫操作的基本函式,這樣可以讓我們在解題上做出不少的簡化,同時也避免打字上的錯誤發生。
函式的設計有很多彈性,我在這邊提供我自己在解題時會用到的幾個自訂函式,主要是把SQL的新增/修改/刪除/查詢做成函式,讓SQL語句參數化,只要帶入參數,函式就會自動拚成需要的語句並取得執行的結果,有興趣的人也可以自己去研究各題組的特性,建立對自己有幫助的函式;另外,由於題目並沒有特別要求要做字串淨化,所以一些檢查是可以先略過不做的。
如果是採用框架來解題的朋友,那麼這一段就可以省了,因為框架大多會先幫你把資料庫的存取封裝好,你只要知道使用方式就好了,針對使用框架的應檢者,我會建議在安裝軟體的時間,先做前端的模版切割,把各題的模版先做好,不然的話使用框架後反而要花很多時間在處理前端的模板,或者完全捨棄官方提供的版型檔案,自己快速刻一個出來也可以。
base檔的建立
我會先建立一個base.php的檔案,這個檔案裏會用來放置共用函式及一些共用變數,這個檔案也會用來include在需要的檔案中,等同於先執行一次這個檔案的內容,方便後續其它程式碼取用。
針對解題需要,base.php中最優先要做的,是把資料庫的連線語法建立起來,這裏我們使用的是PDO的連線語法,看起來會像這樣:
$dsn="mysql:host=localhost;charset=utf8;dbname=db01";
$pdo=new PDO($dsn,"root","");
session_start();
我會再加上一句session_start()的原因是解題過程中會頻繁的利用session來處理資料,所以寫在這裏,可以讓網頁一被執行時就啟用session的功能。
1.numRows($table,$data) - 資料筆數函式
這個函式是用來計算資料列數的,只要指定資料表及條件,就可以算出有幾筆資料,條件的部份我分成有條件和沒有條件兩種狀況,如果是沒有條件的話,那就是要計算全部的列數,如果是有條件的話那就是計算符合條件的列。
由於乙級的題組很少有條件非常複雜的查詢,因此我在設計共用函式時,只有針對解題上比較常有的狀況去設計,比如條件都是AND的型式,不包含OR或子查詢的情形.
這個函式會先判斷$data是否為陣列,以此來做為一種狀況的判斷,然後再根據不同的狀況去執行不同的工作,這樣的設計方式可以提高單一函式的可用性,不需要為了不同的狀況而撰寫多個函式;採用陣列的方式做為條件也是同樣的思考,因為查詢條件可能有很多種組合,如果每一種組合都單獨寫一個函式,那其實和直接寫原生的查詢語句沒什麼不同;因此設計共用函式的基本精神就是要考慮到能簡化到什麼程度,以及是否可以真的減少解題的時間。
函式命名的部份我個人習慣用駝峰式的命名法,不過如果在意時間的話,可以全用小寫也可以。
以這個計數函式來說,當我以numRows('title','')來呼叫時,由於第二個參數不是陣列,所以會回傳整張'title'資料表的資料筆數,或是以文字方式帶入的語句,比如第三題需要計算三天內的上映影片,這邊會帶入特別的查詢語句('where sh=1 && ondate >= '".$ondate."' && ondate
<='".$today."' order by rank ');其他狀況則是需要有一個欄位或兩個以上欄位符合時傳回列數,因為我使用迴圈來組合多種條件,所以不管條件有幾個,都可以只用一個函式來求筆數;以下的函式都是差不多的設計精神。
2.find($table,$seq) - 取得單筆資料
這個函式是用來取得指定序號的單筆資料用的,因為有很多的小題是針對單一筆資料進行編輯的動件,只要傳入資料表和資料的序號,這個函式就可以回傳整筆資料。
3.all($table) - 全部資料
這個函式會直接回傳整張資料表的全部資料,很多後台的功能都是把全部的資料顯示出來,套用這個函式可以很快的取得全部的資料,不用再下SQL語法。
4.where($table,$str) - 查詢資料
這個函式,可以提供在where條件句後的內容,如果是要增加order by 或limit之類的條件句,只要先接上 true就可以了,另外,由於回傳的資料可能只有一筆也可能多筆,因此這個函式不做fetch的動作,視狀況自己決定是要fetchAll()還是fetch()甚至也可以用fetchColumn()。
條件句的部份也可以設計成根據陣列或字串來做不同的動作,但我評估後,解題需要的條件都相對簡單,直接下語法也不會太慢,這部份就見人見智了,因為要寫一個很聰明多工的函式其實也要花不少時間,如果使用的頻率不高的話,那對解題其實沒什麼幫助。
5.insert($table,$data) - 新增資料
這個函式的功能很簡單,就是單純的新增一筆資料就好,針對解題,我僅量設計的簡單一些,需要塔配資料表的設計來使用,比如有些欄位需要有預設值,這樣我在新增資料時,只需要針對表單送來的資料欄位做處理就可以了,不需要顧慮每一個欄是否都要填值。
6.update($table,$data) - 更新資料
更新資料的函式設計的比較複雜一些,主要是考量到有些小題的更新條件比較複雜,否則在大多數的狀況下,更新資料會是以序號為條件。
這邊把陣列的內容拆成'set'和'where'兩個子陣列,這樣的設計是為在建立資料時比較好理解那個子陣列是在做什麼用的,而'where'中如果傳入的是陣列的話,則預設全部條件都是' && '的狀況,
7.delData($table,$data) - 刪除資料
刪除資料的函式也會判斷傳入的資料是陣列或非陣列,如果是非陣列的話,則預設是傳入資料序號,大多數的狀況會以傳入序號為主,所以如果想省下撰寫函式的時間的話,也可以把這個函式再精簡。
8.q($table,$str) - 通用查詢函式
這個函式只是為了節省一些打字量而設計的,同時也算是對其它函式無法做到的功能所做的一個備案,像是需要用到sum()這類聚合函數的場合,就會使用這個函式來處理;
除了這幾個函式是解題一開始會先寫好之外,針對各題,也可能會有不同的自訂函式可以再做簡化,比如第一題及第四題的選單都可以另外設計一個函式來使用會比較理想,至於最終要設計多少個共用函式來協助解題,就看每個人對題目的理解來決定。