簡單的SQL Builder類別

 Wed, 17 Oct 2007 14:25:31 +0800

昨天檢視了一下以前寫的程式,想要改良一下程式的效率,並且讓程式清晰易懂。這個時候發現一個問題,就是依照條件建構SQL的過程太複雜,需要許多if/else判斷,使得程式容易不小心出錯。

仔細觀察了一下,問題發生的主要原因在於兩個地方:

  1. SQL子句有固定的順序,但是程式邏輯不一定符合這個順序
  2. 查詢的條件必須集中在Where子句中,但是形成這些條件的過程不一定是集中的

結果為了依照SQL的規則來產生SQL語句,就會讓程式流程變得很複雜。

想到的方法是,將sql語法的邏輯與產生sql的邏輯分開,寫一個類別,任意將各種條件傳入,等到需要用到SQL語句時,再依照SQL語法來將各種條件組合成SQL語句。依照這個想法,寫了一個簡單的SQL Builder類別:

class QueryBuilder {
var $table;
var $columns;
var $active;
var $order;
var $where;
var $limit;
function QueryBuilder ($table, $columns) {
$this->__construct ($table, $columns);
}
function __construct ($table, $columns) {
$this->table = $table;
if (strpos($columns,':')===false) {
$this->columns = array($columns);
} else {
$this->columns = explode(':',$columns);
}
$this->where = array();
$this->order = "";
$this->limit = "";
}
function setActive ($active) {
$this->where[] = " $active=1";
}
function setOrder ($order, $sort="ASC") {
$this->order = sprintf(" ORDER BY %s %s", $order, $sort);
}
function setWhereInt ($col, $val) {
$this->where[] = sprintf(" %s=%u", $col, intval($val));
}
function setWhereStr ($col, $val) {
$this->where[] = sprintf("%s='%s'", $col, $val);
}
function setSearch ($col, $val) {
$this->where[] = sprintf("%s LIKE '%%s%'", $col, $val);
}
function setSearchLt ($col, $val) {
$this->where[] = sprintf("%s < %u", $col, intval($val));
}
function setSearchGt ($col, $val) {
$this->where[] = sprintf("%s > %u", $col, intval($val));
}
function setLimit ($offset,$rowcount) {
$this->limit = " LIMIT $offset, $rowcount";
}
function compose () {
$ret = sprintf("SELECT %s FROM %s", implode(',',$this->columns), $this->table);
if ($this->where) {
$ret .= sprintf(" WHERE %s", implode(' AND ', $this->where));
}
$ret .= $this->order;
$ret .= $this->limit;
return $ret;
}
}

這個類別還很粗糙,但是剛好滿足我的需求,也讓程式流程看起來比較清楚了。