gusucode.com > 同城苏州黄页系统php源码程序 > lib/Query.class.php
<? /** * 用于設置多樣條件,並完成數據庫查詢的類,2005/7/19 整理 * * @author alee <alee201@163.com> * @version 1.1.0 2005/7/19 第一个稳定版本,具备基本功能 * @version 1.1.1 2005/7/20 修正了getCnt()函數在dbtable屬性爲數組的情況下,如果結果為0,被認定出錯 * @version 1.2.0 2005/8/10 增加了union 聯合查詢時,爲不同數據表指定不同的字段 * @version 1.2.1 2005/9/2 增加了set_regexp 方法 * @version 1.2.2 2005/9/5 directCondition方法增加了field 參數 * @version 1.2.3 2005/9/8 增加了dateCondition 方法,修正了mathCondition方法 * @version 2.0.1 2005/10/18 增加了 條件組,Query.class 的內部機制 發生了很大的變化,所以 版本號定爲 2.x ,以示區別 * @version 2.1.0 2005/10/21 增加了 currentTable 屬性 和 相關的 setCurTable()/ clearCurTable() 兩個函數,以支持 在 union 查詢時 可爲 不同的 table 指定不同的條件。設置條件前,使用 setCurTable() 指明該條件 僅作用于那些 數據表 , 設置完畢 可使用 clearCurTable() 清除 * @version 3.0.0 2005/10/26 修改了 get_result() 的调用参数,因此不再向下兼容 * @version 3.1.0 2005/10/28 增加了 save() 和 revert() 函数 * @package Query Class 數據庫條件查詢類 */ class Query { /** * @ignore */ var $logic = ""; /** * 連接多次利用directCondition()、set_like()等函數設定的條件的邏輯關系 * * 前後必須有一個空格,以便直接在sql中使用,如:<code>$q->cut=" and ";</code> * * @var string " and "," or " * @see areaCondition() * @see directCondition() * @see mathCondition() * @see set_keyworld() * @see set_like() * @see set_where() */ /** * @ignore */ var $sql = ""; /** * @ignore */ var $dbtable = array(); var $tempTableName = ''; /** * @ignore */ var $primaryKey = "id"; /** * @ignore */ var $order_sql = ""; /** * @ignore */ var $limit_sql = ""; var $noLimit = false; /** * @ignore */ var $limit_len = 30; /** * @ignore */ var $returnFlds = "*"; /** * @ignore * 所有字段,他是 $publicFld的元素值 和 $privateFld的鍵名,以及sql where子句中出現的字段名 的合集 */ var $totalFld = array(); /** * @ignore * 公共字段,在多個數據表中使用 */ var $publicFld = array(); /** * @ignore * 私有字段,僅在個別數據表中 */ var $privateFld = array(); /** * @ignore */ var $where = ""; var $conditions = array( 'type' => 'group', 'name' => 'root', 'logic' => ' AND ', 'level' => 0, 'member'=> array() ); var $conditionIndex = array(); var $currentGroup = null; var $selectOrd = array(); var $save; /** * 當 調用 $this->condition() 和 其它設置條件的 函數時,如果沒有指定 數據表,則使用此變量,說明設置的條件 作用的數據表 * * @var unknown_type */ var $currentTable = array(); // private function ============================================= function setFld($fldList) { # 清空變量 $this->totalFld=array(); $this->privateFld=array(); $this->publicFld=array(); if(!is_array($fldList)) $fldList=array($fldList); foreach ($fldList as $key=>$item) { if(!is_array($item)) $this->totalFld[]=$this->publicFld[]=$item; else { $this->totalFld[]=$key; $this->privateFld[$key]=$item; } } } function getFld($table) { if( $this->publicFld == '*' ) return $this->returnFlds='*'; if( count($this->publicFld)==1 and $this->publicFld[0]=='*' ) return $this->returnFlds='*'; # 共有字段 $pubFlds = array(); foreach ($this->publicFld as $item) $pubFlds[] = "`$item`"; # 分別私有字段 $spFlds = array(); foreach ($this->privateFld as $key=>$item) { if( in_array($table,$item) or $table==$this->tempTableName) $spFlds[] = "`{$key}`"; elseif( (is_array($this->dbtable) and count($this->dbtable)>1) ) $spFlds[] = "'' as `{$key}'"; else continue; } // 合併 公共字段 $flds = array_merge($pubFlds,$spFlds); // 合並共有和私有字段,並返回 return $this->returnFlds=implode(",",$flds); /*# 分別私有字段 $spFlds=''; foreach ($this->privateFld as $key=>$item) { if( in_array($table,$item) or $table==$this->tempTableName) $spFlds.=(empty($spFlds)?null:',').'`'.$key.'`'; elseif( (is_array($this->dbtable) and count($this->dbtable)>1) ) $spFlds.=(empty($spFlds)?null:',')."'' as `".$key.'`'; else continue; } // 合併 公共字段 $pubFlds="`".implode("`,`",$this->publicFld)."`"; // 合並共有和私有字段,並返回 if( !empty($pubFlds) and !empty($spFlds)) return $this->returnFlds=$pubFlds.','.$spFlds; else return $this->returnFlds=$pubFlds.$spFlds; */ } # 如果存在 私有 字段,在數據庫中 創建一個臨時表,以便于 union 查詢時,使用相同的 field list function createTempTable_4_union() { if(count($this->privateFld)) { // 獲得條件子句中的 字段 if(preg_match_all("/`([^`]+)`[^\.]?/",$this->make_where(),$regr)) { foreach ($regr[1] as $item) { if( !in_array($item,$this->totalFld) ) $this->totalFld[]=$item; } } $this->tempTableName='tmp_table4union_'.(rand(0,10000)*rand(0,10000)); $creat_Temp="CREATE TEMPORARY TABLE {$this->tempTableName} ("; foreach ($this->totalFld as $key=>$fn) { if($key>0) $creat_Temp.=','; $creat_Temp.="\n`{$fn}` text NOT NULL"; } $creat_Temp.="\n);"; $this->Execute_SQL( __FUNCTION__ , $creat_Temp ); return array_merge(array($this->tempTableName),$this->dbtable); } else return $this->dbtable; } function ifIgnoreCondition($value) { if( $value=='' or $value=='-ignore-' ) return true; else return false; } /** * @ignore */ function condition( $sql,$table=array() ) { $sql = trim($sql); if( empty( $sql ) ) return ; if( !empty($this->currentTable) ) // 使用全局屬性 $table=$this->currentTable; if( empty($table) ) // 如果未指定 參數 $table 和 $this->currentTable ,則該條件 作用于全部 數據表 $table=$this->dbtable; $this->currentGroup['member'][] = array( 'type' => 'condition', 'table' => $table, 'sql' => ' ( '.$sql.' ) ' ); } function get_where( $table = null ) { $where=$this->make_where( null,$table ); if( empty($where) ) $where="1"; return $where; } function make_where($group=null,$table=null) { ($group===null)?$group=$this->conditions:null; // 如果未指定條件組,則使用全部 if( count($group['member'])==0 ) return ''; $cds=array(); foreach ( $group['member'] as $theMmb ) { // 條件組成員 if( $theMmb['type'] == 'group' ) { if( ( $w=$this->make_where($theMmb) )=='' ) // 遞歸獲得 條件組成員 的 where子句 continue; // 如果此 條件組成員 返回的 子句爲空,則忽略次成員 $cds[] = $w; } // 條件成員 else { if( empty($theMmb['sql']) ) continue; if( $table and !in_array($table,$theMmb['table']) ) // 該條件 不可用于 指定的數據表 continue; $cds[]=$theMmb['sql']; } } if( !count($cds) ) // 返回空值 return ''; $rstr = "\r\n"; $rstr.= "\r\n" . str_repeat("\t",$group['level']) . "-- Condition Group: \"{$group['name']}\" Start --"; $rstr.= "\r\n(\r\n"; $rstr.= implode( $group['logic'],$cds ); $rstr.= "\r\n)\r\n"; $rstr.= "\r\n" . str_repeat("\t",$group['level']) . "-- Condition Group: \"{$group['name']}\" Over --"; $rstr.= "\r\n"; return $rstr; } /** * 獲取相關記錄數 * * @param string $type 返回類型:"total" * @return integer */ function getCnt($type="total") { $cnt=0; $tablebac=$this->dbtable; foreach($this->dbtable as $table) { $this->make_sql($this->primaryKey,true,$table); $re = $this->Execute_SQL( __FUNCTION__ ); $arr=@mysql_fetch_assoc($re); $cnt+=intval($arr["queryResultCnt"]); } if($cnt!=="") { $result=intval($cnt); if( $type=="thisPge" and $result>$this->limit_len ) return $this->limit_len; else return $result; } else return -1; } // # 檢驗一個字段是否存在 // function field_exists($table) // { // $r=mysql_query("select * from `$table` limit 0,1"); // // mysql_field_name($r); // } // public function ============================================= /** * 構造函數,初始化一些屬性 * * @param string、array $dbtable 需查詢的數據表,如果使用array類型變量傳遞多個數據表,則make_sql()函數將使用union 進行聯合查詢 * @param unknown_type [$logic] 查詢邏輯,true 爲匹配,false 爲過濾 * @param unknown_type [$primaryKey] 數據表主鍵鍵名 * @return void */ function Query($dbtable="post",$logic=true,$primaryKey="id") { $this->dbtable=$dbtable; if( !is_array($this->dbtable) ) $this->dbtable=array($this->dbtable); $this->logic=$logic; $this->primaryKey=$primaryKey; // 初始化 條件組 索引 $this->clearCondition(); } /** * 設置 "字段='值'" 類型的直接條件,可一次設置多個條件,可重複調用,直到使用get_result() * * 用例: * <code># 網頁上有多個 表單: * <form>查詢條件:<br> * 作者:<input name="directCondition[author]" type="text"> * 欄目:<select name="directCondition[class]"> * <option value="class1">時事政治</option> * <option value="class2">焦點訪談</option> * </select> * </form> * .. * # 服務器接受查詢的 php 腳本: * <? * $q=new Query("news"); * $q->directCondition($_POST["directCondition"]); * $a=$q->get_result(); * dump_var($a); * ?> * </code> * * @param array $Condition 數組的鍵名作爲條件的字段名,數組的元素值爲條件的值 * @param string $logic 多個條件之間的邏輯關系 * @param boolean $ingEmpty 是否忽略空值的數組元素 * @return void */ function directCondition($Condition,$logic=" AND ",$ingEmpty=true,$field='') { if( !is_array($Condition) ) exit("Query::directCondition 的參數 \$Condition 必須爲數組。<br>"); if($this->logic) $operator="="; else $operator="!="; $thisC=""; foreach ($Condition as $fld=>$value) { if(!empty($field)) $fld=$field; if( $ingEmpty and $this->ifIgnoreCondition($value) ) continue; if($thisC) $thisC.=" $logic "; $thisC.="(`$fld` $operator '$value')"; } if(empty($thisC)) $thisC='1'; $this->condition($thisC); return $thisC; } /** * 設置全文匹配 like 字句 * * 用例1:在文章正文字段`txt`中查詢“外灘”: * <code>$q->set_like(array("txt"=>"外灘"))</code> * 用例2:在文章正文字段`txt`中查詢“外灘”或“淮海路” * <code>$q->set_like(array("外灘","淮海路")," or ","txt")</code> * * @param array $Condition 數組,每個元素采用:"字段名"=>"條件值",可設置多個like子句 * @param string [$logic] 各 like 子句之間的邏輯值 * @param string $feild 若$Condition 需要在同一個字段設置多個like子句,則此參數說明爲何字段,它將導致$Condition 裏的鍵名沒有作用 */ function set_like($Condition,$logic=" AND ",$feild="") { if( !is_array($Condition) ) exit("Query::set_like 的參數 \$Condition 必須爲數組。<br>"); if($this->logic) $operator="LIKE"; else $operator="NOT LIKE"; $thisC=""; foreach ($Condition as $fld=>$value) { if( empty($value) ) continue; if($thisC) $thisC.=" $logic "; if(empty($feild)) $thisC.="(`$fld` $operator '%$value%')"; else { if(is_array($feild)) $thisC.="(`{$feild[$fld]}` $operator '%$value%')"; else $thisC.="(`$feild` $operator '%$value%')"; } } $this->condition($thisC); } /** * 設置 RegExp 字句 * * @param array $Condition 數組,每個元素采用:"字段名"=>"條件值(正則表達式)",可設置多個like子句 */ function set_regexp($Condition) { if( !is_array($Condition) ) exit("Query::set_like 的參數 \$Condition 必須爲數組。<br>"); if($this->logic) $operator="REGEXP"; else $operator="NOT REGEXP"; $thisC=""; foreach ($Condition as $fld=>$value) { if($thisC) $thisC.=" {$this->logic} "; $thisC.="(`$fld` $operator '%$value%')"; } $this->condition($thisC); } /** * 設置關鍵詞 * * 多個關鍵詞之間可用參數 $keyworlds_logic 來指明邏輯關系;被查詢的字段之間爲邏輯或關系,即一個關鍵詞在其中任何一個字段中出現,即符合條件。 * 用例,在軟件下載系統中查詢"windows 2000":<code>$q->set_keyworld(array("windows","2000","下載"),array("softIntro","softTitle"),"and");</code> * * @param array $keyworlds 關鍵詞,必須爲數組,可設置多個 * @param array $keyworlds4flds 關鍵詞將在被用于查詢的字段,必須爲數組 * @param string $keyworlds_logic 關鍵詞之間的邏輯關系 */ function set_keyworld($keyworlds,$keyworlds4flds,$keyworlds_logic="or") { if( !is_array($keyworlds) or !is_array($keyworlds4flds) ) exit("Query::set_keyworld 的參數 \$keyworlds,\$keyworlds4flds 必須爲數組。<br>"); if($keyworlds_logic!="or" and $keyworlds_logic!="and") exit("Query::set_keyworld 的參數 \$keyworlds_logic 必須爲 \"or\" 或 \"and\"。$keyworlds_logic<br>"); if($this->logic) $operator="LIKE"; else $operator="NOT LIKE"; $thisC=""; foreach($keyworlds as $thekey) { if(!empty($thisC)) $thisC.=" {$keyworlds_logic} "; $thisC.="( "; $thisFldSql=""; foreach($keyworlds4flds as $theFld) { if( !empty($thisFldSql) ) $thisFldSql.=" or "; $thisFldSql.="(`$theFld` $operator '%$thekey%')"; } $thisC.=$thisFldSql." )"; } $this->condition($thisC); } /** * 設置 整數或浮點 字段條件 * * 用例:字段`id`大于等于10的記錄 * <code>$q->mathCondition(array("id"=>"10"),">=")</code> * * @param array $Condition 數組,每個元素采用:"字段名"=>"條件值",可設置多個條件 * @param string $type 條件類型,可以有以下選擇:“<”、“>”、“=”、“<=”、“>=” * @param string [$logic] 多個條件之間的邏輯關系 */ function mathCondition($Condition,$type,$logic=" AND ",$column='') { if( !is_array($Condition) ) exit("Query::mathCondition 的參數 \$Condition 必須爲數組。<br>"); if(!is_array($type)) $type=array($type); $thisC=""; $idx=0; foreach ($Condition as $fld=>$value) { if( preg_match('/^\d*$/',$fld) ) $fld=$column; if( $type[$idx]!="<" && $type[$idx]!="<" && $type[$idx]!="=" && $type[$idx]!="<=" && $type[$idx]!=">=") exit("Query::mathCondition 的參數 \$type 必須爲:“<”、“>”、“=”、“<=”、“>=”。<br>"); if(!$this->logic) // 過濾 { switch($type[$idx]) { case "<": $operator=">="; break; case ">": $operator="<="; break; case "=": $operator="!="; break; case ">=": $operator="<"; break; case "<=": $operator=">"; break; } } else // 匹配 $operator=$type[$idx]; if($thisC) $thisC.=$logic; $thisC.="(`$fld` $operator $value)"; $idx++; } $this->condition($thisC); } /** * 設置“10-100”格式的範圍條件 * * 參數 $value 的格式 可以爲以下三種類型:“數字-”,“-數字”,“數字-數字”。 * <code>// `id` 大于 10 的記錄 * $q->areaCondition("id","10-"); * * // `id` 小于 100 的記錄 * $q->areaCondition("id","-100"); * * // `id` 大于 10,小于 100 的記錄 * $q->areaCondition("id","10-100"); * </code> * * @param string $fld 查詢的字段名 * @param string $value 範圍,必須爲 "[數字]-[數字]" 格式 * @return boolean 當參數無效時,返回false,否則無論查詢結果如何,由此産生的sql是否正確,均返回true,僅表示條件設置成功 */ function areaCondition($condition,$value='') { if(!is_array($condition)) $condition=array($condition=>$value); foreach ($condition as $fld=>$value) { if( $this->ifIgnoreCondition($value) ) continue; if( isset($value) and preg_match("/^(\d+\-\d+)|(\d+\-)|(\-\d+)$/",$value) ) { $value=explode("-",$value); # 類如 20-63,則取20到63只閒的值 if( $value[0]!=='' and $value[1]!=='' and $value[0]<=$value[1] ) $this->mathCondition(array($value[0],$value[1]),array(">=","<=")," and ",$fld); # 類如 23-14,則取 負無窮到14,23到正無窮的合集 elseif ($value[0]!=='' and $value[1]!=='' and $value[0]>$value[1]) $this->mathCondition(array($value[0],$value[1]),array(">=","<=")," or ",$fld); elseif ($value[0]==='' and $value[1]!=='') # 類如 -45 ,則取45以下的集合 $this->mathCondition(array($fld=>$value[1]),"<="); elseif ($value[0]!=='' and $value[1]==='') # 類如 65- ,則取65以上的集合 $this->mathCondition(array($fld=>$value[0]),">="); } else return false; } return true; } function set_where($sql) { $this->condition( $sql ); } /** * 設置 返回記錄的排列方式,及設置 ORDER BY 子句 * * @param string $fld 按照哪一個字段來排列 * @param string $order 排列順序,缺省爲有小到大,或使用“desc”有大到小 */ function set_order($fld="id",$order="") { if( is_array($fld) ) $fld = implode( '`,`', $fld ) ; $this->order_sql=" ORDER BY `$fld` $order"; } /** * 設置 LIMIT 子句,通常是爲了實現分頁,Query 中有專門設施分頁的函數 set_page() * * @param integer [$len] 返回長度,用作limit 字句中第二個參數 * @param integer [$start] 其實記錄數,從零開始,用作limit 字句中第一個參數 * @see set_page() */ function set_limit($len=1,$start=0) { $this->limit_len=$len; $this->limit_sql="LIMIT $start,{$this->limit_len}"; } /** * 設置分頁 及當前頁碼,它通過 SQL 的 LIMIT 子句實現 * * @param integer $recordPerPge 每頁記錄數 * @param integer [$pgeNum] 當前第幾頁 * @see set_limit() */ function set_page($recordPerPge,$pgeNum=1) { $start=$recordPerPge*($pgeNum-1); $len=$recordPerPge; $this->limit_sql="LIMIT $start,$len"; } /** * 查詢並返回結果集,它返回三種形式的結果:數組、xml、serialize()序列化以後的數組 * * 如果第三個參數采取默認值,則返回二維數組,僅包含元素[records]的內容,記錄集結構如下 * <code> array( * [0] =>array( * [field1]=>"", * [field2]=>"", * [field3]=>"", * [field4]=>"" * ), * [1] =>array( * [field1]=>"", * [field2]=>"", * [field3]=>"", * [field4]=>"" * ), * …… * ) * </code> * 如果第三個參數爲 true ,則返回三維數組,第一維包含四個元素: * [records] (或第四個參數指定的鍵值)記錄集; * [totalCnt] 記錄總數; * [thisPgeCnt] 當前分頁記錄數; * [totalPgeCnt] 分頁總數 * * @param array、string [$returnFlds] 需返回的字段 * @param string [$returnType] 返回值類型:"array","xml","serialize" * @param string [$returnKey] 如果返回記錄數量,記錄集的鍵值,或返回 xml 結構中 * @return array,string(xml),string(array serialize) 返回數組、xml格式字串、serialize()序列化數組後的字串 */ function get_result(&$result_set,$returnFlds=array("*"),$returnType="array") { $this->make_sql($returnFlds); // 产生sql $result=$this->Execute_SQL(__FUNCTION__,$this->sql); // 执行查询 $result_set=array(); while($array=mysql_fetch_assoc($result)) { if(!empty($returnKey) and $ifCnt) $result_set[$returnKey][]=$array; else $result_set[]=$array; } // 获得数据集 switch ($returnType) { case "xml": $returnxml="<?xml version=\"1.0\" encoding=\"gb2312\"?>\n<postCollection>\n"; foreach($result_set as $thepost) { $returnxml.="\t</post>\n"; foreach ($thepost as $fld=>$value) $returnxml.="\t\t<$fld>$value</$fld>\n"; $returnxml.="\t</post>\n"; } $returnxml.="</postCollection>"; $result_set = $returnxml; break; case "serialize": $result_set = serialize($result_set); break; default: break; } $return["totalCnt"]=$this->getCnt("total"); $return["thisPgeCnt"]=count( $result_set ); $return["totalPgeCnt"]=ceil( $return["totalCnt"] / $this->limit_len ); return $return; } /** * dateCondition 設置日期條件 * * param string、array $startTime 開始時刻 格式:"2005-9-24 12:55:12" 或 array([y]=>2005,[m]=>9,[d]=>24,[G]=>12,[i]=>55,[s]=>12) 年月日時分秒 各參數均可省略,第一種形式 可滿足用戶 在 文本框中 直接填寫日期,第二種 形式,可滿足用戶通過下拉菜單填寫日期 * param string、array $endTime 結束時刻 各式同 $startTime */ function dateCondition($field,$startTime,$endTime='') { if(!is_array($startTime) ) { if( preg_match("/^\d{10}$/i",$startTime) ) $startTime = date('Y-m-d G:i:s',$startTime); if( !preg_match("/^((\d{4})(\-(\d{1,2})(\-(\d{1,2})( (\d{1,2})(:(\d{1,2})(:(\d{1,2}))?)?)?)?)?)?$/",$startTime,$r) ) exit("Query::dateCondition()函數的參數必須為數組、2004-6-24 23:12:24 格式字符串、或Unix 时间戳。"); $startTime=array( 'y'=>@$r[2], 'm'=>@$r[4], 'd'=>@$r[6], 'G'=>@$r[8], 'i'=>@$r[10], 's'=>@$r[12], ); } if(!is_array($endTime) ) { if( preg_match("/^\d{10}$/i",$endTime) ) $endTime = date('Y-m-d G:i:s',$endTime); if( !preg_match("/^((\d{4})(\-(\d{1,2})(\-(\d{1,2})( (\d{1,2})(:(\d{1,2})(:(\d{1,2}))?)?)?)?)?)?$/",$endTime,$r) ) exit("Query::dateCondition()函數的參數必須為數組、2004-6-24 23:12:24 格式字符串、或Unix 时间戳。"); $endTime=array( 'y'=>@$r[2], 'm'=>@$r[4], 'd'=>@$r[6], 'G'=>@$r[8], 'i'=>@$r[10], 's'=>@$r[12], ); } if( empty($startTime['y']) ) $st=''; elseif ( empty($startTime['m']) ) $st=mktime(0,0,0,0,0,$startTime['y']); elseif ( empty($startTime['d']) ) $st=mktime(0,0,0,$startTime['m'],0,$startTime['y']); elseif ( empty($startTime['G']) ) $st=mktime(0,0,0,$startTime['m'],$startTime['d'],$startTime['y']); elseif ( empty($startTime['i']) ) $st=mktime($startTime['G'],0,0,$startTime['m'],$startTime['d'],$startTime['y']); elseif ( empty($startTime['s']) ) $st=mktime($startTime['G'],$startTime['i'],0,$startTime['m'],$startTime['d'],$startTime['y']); else $st=mktime($startTime['G'],$startTime['i'],$startTime['s'],$startTime['m'],$startTime['d'],$startTime['y']); if( empty($endTime['y']) ) $et=''; elseif ( empty($endTime['m']) ) $et=mktime(23,59,59,12,30,$endTime['y']); elseif ( empty($endTime['d']) ) $et=mktime(23,59,59,$endTime['m'],30,$endTime['y']); elseif ( empty($endTime['G']) ) $et=mktime(23,59,59,$endTime['m'],$endTime['d'],$endTime['y']); elseif ( empty($endTime['i']) ) $et=mktime($endTime['G'],59,59,$endTime['m'],$endTime['d'],$endTime['y']); elseif ( empty($endTime['s']) ) $et=mktime($endTime['G'],$endTime['i'],59,$endTime['m'],$endTime['d'],$endTime['y']); else $et=mktime($endTime['G'],$endTime['i'],$endTime['s'],$endTime['m'],$endTime['d'],$endTime['y']); $this->areaCondition($field,"$st-$en"); } /** * 組裝 SQL 語句,get_result(),getCnt() 會首先調用此函數獲得sql * * @param array、string $returnFlds 需要返回的字段,多個字段可用數組,單個字段可用字串 * @param boolean $getCnt 是否僅返回記錄數,此參數將導致參數 $returnFlds 無效 * @param string $table 當 $getCnt = true 時 此參數有效,說在返回 那一個 數據表的 記錄數 * @return string 返回一個sql語句 */ function make_sql($returnFlds=array("*"), $getCnt=false, $table='') { $this->setFld($returnFlds); if($getCnt) { if( empty($table) ) $table = $this->dbtable[0]; $where = $this->get_where( $table ); return $this->sql="\r\n-- In table `{$table}` \r\nSELECT count(`{$this->primaryKey}`) as `queryResultCnt` FROM `{$table}` WHERE {$where}"; } else { if( !$this->noLimit and empty($this->limit_sql) ) $this->set_page(30); if( count($this->dbtable) > 1 ) # 多個數據表 利用 union 聯合查詢 { $this->sql=""; $dbtable=$this->createTempTable_4_union(); foreach($this->dbtable as $theTab) { $where = $this->get_where($theTab); if(!empty($this->sql)) $this->sql.="\nUNION\n"; $this->getFld($theTab); $this->sql.="(\r\n-- In table `{$theTab}` \r\nSELECT {$this->returnFlds} FROM `{$theTab}` WHERE {$where}\n)"; } $this->sql.="\n{$this->order_sql} {$this->limit_sql}"; } else # 單一數據表查詢 { $where = $this->get_where( $this->dbtable[0] ); $this->getFld( $this->dbtable[0] ); $this->sql="\r\n-- In table `{$this->dbtable[0]}` \r\nSELECT {$this->returnFlds} FROM `{$this->dbtable[0]}` WHERE {$where} {$this->order_sql} {$this->limit_sql}"; } return $this->sql; } } function addGroup($name=null,$logic=' or ') { if( $name==null ) $name='ConditionGroup_'.( count( $this->conditionIndex )+1 ); if( key_exists($name,$this->conditionIndex) ) { print "\r\n<br />".__CLASS__."::".__FILE__."() 遇到錯誤:名爲 {$name} 的條件組已經存在,不能創建名稱相同的條件組。\r\n<br \>"; exit(); } $new_grp=array( 'type' => 'group', 'name' => $name, 'logic' => strtoupper($logic), 'level' => $this->currentGroup['level'] + 1, 'member'=> array() ); $this->currentGroup['member'][$name] = $new_grp; // 注冊新增的條件組 $this->conditionIndex[$name] = &$this->currentGroup['member'][$name]; // 設置爲 當前條件組 $this->select_group($name); } function select_group($name) { if( !isset($this->conditionIndex[$name]) ) { print "\r\n<br />".__CLASS__."::".__FILE__."() 遇到錯誤:制定的條件組 {$name} 尚未創建。\r\n<br \>"; exit(); } $this->currentGroup = &$this->conditionIndex[$name]; // 重設當前使用 條件組 的路徑 if( ( $idx=array_search($name,$this->selectOrd) )!==false ) $this->selectOrd = array_slice($this->selectOrd,0,$idx+1); else $this->selectOrd[]=$name; } function back() { if( count( $this->selectOrd )>1 ) { array_pop( $this->selectOrd ); $name = end($this->selectOrd); $this->currentGroup = &$this->conditionIndex[$name]; return true; } else return false; } function today($fld) { $start=mktime( 0,0,0,date('m'),date('d'),date('Y') ); $end=mktime( 23,59,59,date('m'),date('d'),date('Y') ); $sql=" `$fld` >= '$start' and `$fld` <= '$end' "; $this->condition($sql); } function setCurTable() { $this->currentTable = func_get_args(); } function clearCurTable() { $this->currentTable = array(); } function Execute_SQL( $function = null , $sql = null ) { if( empty($sql) ) $sql = $this->sql ; if( $re=mysql_query($sql) ) return $re; else { print __CLASS__.'::'.__FUNCTION__."() 函數在執行一條".(empty($function)?'':'由'.__CLASS__."::{$function}()函數傳遞的 ")." SQL 語句時遇到錯誤:".mysql_error()."\r\n\r\n<br /><br />正在執行的 SQL 爲:\r\n<br />".$sql; exit(); } } function setGroupLogic($logic=' OR ',$group=null) { if( empty($group) ) $group=&$this->currentGroup; else $group=&$this->conditionIndex[$group]; $group['logic']=strtoupper($logic); } function clearCondition() { $this->conditions=array( 'type' => 'group', 'name' => 'root', 'logic' => ' AND ', 'level' => 0, 'member'=> array() ); $this->conditionIndex = array( 'root'=>& $this->conditions ); $this->currentGroup = & $this->conditions; $this->selectOrd = (array)'root'; $this->order_sql=''; $this->limit_sql=''; $this->privateFld=array(); $this->publicFld=array(); $this->totalFld=array(); $this->tempTableName=''; $this->sql=''; } function save() { $this->save = serialize($this) ; } function revert() { $this = unserialize($this->save) ; } } $Query_class_declare=true; ?>