💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
1. 类文件位置 Core/lib/sqlbuild.php ms_sqlbuild ~~~ <?php define("MF_DB_J",'JOIN'); define("MF_DB_LJ",'LEFT JOIN'); define("MF_DB_RJ",'RIGHT JOIN'); /** * 用于sql语句组合 */ class ms_sqlbuild { //所支持的组合子句集合 protected $var_fields = array('set', 'select', 'from', 'index', 'where', 'group_by', 'having', 'order_by', 'limit'); public $table = ''; public $where = ''; public $set = ''; public $select = ''; public $from = ''; public $index = ''; public $group_by = ''; public $having = ''; public $order_by = ''; public $limit = ''; //缓存 public $cache_table = ''; public $cache_where = ''; public $cache_select = ''; public $cache_from = ''; public $cache_index = ''; public $cache_group_by = ''; public $cache_having = ''; public $cache_order_by = ''; public $cache_limit = ''; //db操作类 protected $db = null; //db类是否继承自activerecord类 protected $is_activerecord = true; /** * 获取操作的DB类 * @param [type] $db [description] */ function __construct($db) { $this->db = $db; //判断这个类是否实例化自 ms_activerecord $this->is_activerecord = get_class($this->db) == 'ms_activerecord'; } // 设置SQL中的from子句 function from($tablename, $asname = null, $sql = null) { $this->from = $this->db->get_table($tablename).($asname ? " $asname" : ''); if($sql) $this->from .= ' '.$sql; return $this->get_class(); } // 关联2个表 function join($table1,$key1, $table2,$key2, $jointype = 'JOIN') { if(!preg_match("/^([a-z0-9]+)\.([a-z0-9_]+)$/i", $key1, $match1)) { redirect('1.无效的关联表字段。'.$key1); } if(!preg_match("/^([a-z0-9]+)\.([a-z0-9_]+)$/i", $key2, $match2)) { redirect('2.无效的关联表字段。'.$key2); } $table1 = $this->db->get_table($table1); $table2 = $this->db->get_table($table2); $asname1 = $match1[1]; $asname2 = $match2[1]; $key1 = $this->db->_ck_field($match1[2]); $key2 = $this->db->_ck_field($match2[2]); $this->from = sprintf("%s %s %s %s %s ON (%s.%s = %s.%s)", $table1, $asname1, $jointype, $table2, $asname2, $asname1, $key1, $asname2, $key2); return $this->get_class(); } // 关联第3,4..个表 function join_together($together_key, $table, $key, $jointype = 'JOIN') { if(!preg_match("/^([a-z0-9]+)\.([a-z0-9_]+)$/i", $together_key, $match1)) { redirect('无效的关联表字段。'.$together_key); } if(!preg_match("/^([a-z0-9]+)\.([a-z0-9_]+)$/i", $key, $match2)) { redirect('无效的关联表字段。'.$key); } $together_asname = $match1[1]; $asname = $match2[1]; $table = $this->db->get_table($table); $together_key = $this->db->_ck_field($match1[2]); $key = $this->db->_ck_field($match2[2]); $this->from .= sprintf(" %s %s %s ON (%s.%s = %s.%s)", $jointype, $table, $asname, $together_asname, $together_key, $asname, $key); return $this->get_class(); } function use_index($index_name) { if(!preg_match("/^([a-z0-9_]+)$/i", $index_name)) { redirect('无效的索引名称。'.$index_name); } $this->index = " ($index_name)"; return $this->get_class(); } // 设置查询字段 function select($fields, $asname = NULL, $fun = NULL) { $split = $this->select ? ',' : ''; if(is_string($fields)) { if($fun) { $fields = str_replace('?', $this->db->_ck_field($fields), $fun); } else { $fields = $this->db->_ck_field($fields); } $select = $fields.($asname ? (' AS '.$this->db->_ck_field($asname)) : ''); $this->select .= $split.$select; } elseif(is_array($fields)) { foreach ($fields as $key) { $this->select .= $split.$this->db->_ck_field($fields); $split = ','; } } return $this->get_class(); } //字段有函数 function select_param($fun, $fields) { if(!is_array($fields)) $fields = array($fields); foreach ($fields as $k => $field) { $fields[$k] = $this->db->_escape($field); } $select = vsprintf($fun, $fields); $this->select .= ($this->select ? ',' : '').$select; return $this->get_class(); } // 设置更新字段或插入字段数据 function set($key, $value=null) { if(is_array($key)) { foreach($key as $k => $v) { if(is_array($v) && count($v)==2 && is_array($v[1])) { $fun = $v[0]; $args = array_merge(array($k), $v[1]); call_user_func_array(array(&$this, $fun), $args); } else { $this->set($k, $v); } } } else { $this->db->_ck_field($key); $this->set[$key] = $this->db->_escape($value); } return $this->get_class(); } // 设置更新2个字段值相同 function set_equal($key1,$key2) { $this->db->_ck_field($key1); $this->db->_ck_field($key2); $this->set[$key1] = $key2; return $this->get_class(); } // 设置更新字段累加 function set_add($key, $value=1) { if(!$value) return; $this->db->_ck_field($key); $this->set[$key] = $key.'+'.$this->db->_escape($value); return $this->get_class(); } // 设置更新字段减少 function set_dec($key, $value=1) { $this->db->_ck_field($key); $this->set[$key] = $key.'-'.$this->db->_escape($value); return $this->get_class(); } // 直接使用SQL表示set的值 function set_src($key, $value) { $this->set[$key] = $key.'-'.$value; return $this->get_class(); } // 设置查询字段 function where($key, $value = '', $split = 'AND') { if(!$key) return $this->get_class(); if(is_array($key)) { foreach ($key as $k => $v) { if(is_array($v) && count($v)==2 && is_array($v[1])) { $fun = $v[0]; $args = array_merge(array($k), $v[1]); call_user_func_array(array(&$this, $fun), $args); } else { $this->where($k, $v, $split); } } } elseif($key=='{sql}') { $this->_exp_where('sql', $value, $split); } elseif(is_array($value)) { $this->where_in($key, $value, $split); } else { $where = $this->db->_ck_field($key)." = ".$this->db->_escape($value); $this->where .= ($this->where ? " $split " : '').$where; } return $this->get_class(); } // 查询字段表达式,用户复杂的where子句 function where_exp($exp, $key, $value, $split='AND') { if(is_array($value)) { foreach($value as $_k => $val) { $value[$_k] = $this->db->_escape($val); } $value = implode(",", $value); } $where = sprintf(str_replace(" ? "," %s ", $exp), $this->db->_ck_field($key), $value); $this->where .= ($this->where ? " $split " : '').$where; return $this->get_class(); } // 设置查询子句形式 field != 'value' function where_not_equal($key, $value, $split='AND') { $where = $this->db->_ck_field($key)." != ".$this->db->_escape($value); $this->where .= ($this->where ? " $split " : '').$where; return $this->get_class(); } // 设置查询子句形式 field >= 'value' 或 field > 'value' function where_more($key, $value, $equal=1, $split='AND') { $mark = $equal ? '>=' : '>'; $where = $this->db->_ck_field($key).$mark.$this->db->_escape($value); $this->where .= ($this->where ? " $split " : '').$where; return $this->get_class(); } // 设置查询子句形式 field <= 'value' 或 field < 'value' function where_less($key, $value, $equal=1, $split='AND') { $mark = $equal ? '<=' : '<'; $where = $this->db->_ck_field($key).$mark.$this->db->_escape($value); $this->where .= ($this->where ? " $split " : '').$where; return $this->get_class(); } // 设置查询子句形式 in function where_in($key, $values, $split='AND') { if(count($values) == 0) return; if(count($values) == 1) { $this->where($key, $values[0], $split); return; } foreach($values as $_key => $_val) { $values[$_key] = $this->db->_escape($_val); } $where = $this->db->_ck_field($key)." IN (". implode(",", $values) .")"; $this->where .= ($this->where ? " $split " : '').$where; return $this->get_class(); } // 设置查询子句形式 not in function where_not_in($key, $values, $split='AND') { foreach($values as $_key => $_val) { $values[$key] = $this->db->_escape($_val); } $where = $this->db->_ck_field($key)." NOT IN (". implode(",", $values) .")"; $this->where .= ($this->where ? " $split " : '').$where; return $this->get_class(); } // 设置查询子句形式 field between 100 and 200 function where_between_and($key, $begin, $end, $split='AND') { $where = $this->db->_ck_field($key)." BETWEEN ". $this->db->_escape($begin) ." AND ".$this->db->_escape($end); $this->where .= ($this->where ? " $split " : '').$where; return $this->get_class(); } // 设置查询子句形式 field like '100%' function where_like($key, $value, $split='AND', $kh = '') { $where = $this->db->_ck_field($key)." LIKE ".$this->db->_escape($value); $this->where .= ($this->where ? " $split " : '').($kh=='('?'(':'').$where.($kh==')'?')':''); return $this->get_class(); } // 设置查询子句形式 or function where_or($key, $value) { if(is_array($value)) { $this->where_in($key, $value, 'OR'); } else { $where = $this->db->_ck_field($key)." = ".$this->db->_escape($value); $this->where .= ($this->where ? ' OR ' : '').$where; } return $this->get_class(); } // 设置查询子句形式 CONCAT(field,field2) like '100%' function where_concat_like($keys, $value, $split='AND', $kh='') { if(is_string($keys)) $keys = explode(',', $keys); foreach($keys as $k=>$v) { $keys[$k] = $this->db->_ck_field(trim($v)); } $where = "CONCAT(".implode(',',$keys).") LIKE ".$this->db->_escape($value); $this->where .= ($this->where ? " $split " : '').($kh=='('?'(':'').$where.($kh==')'?')':''); return $this->get_class(); } // 设置exist子查询 function where_exist($sql, $split='AND', $kh = '') { $where = 'exists(' .$this->db->repace_table($sql).')'; $this->where .= ($this->where ? " $split " : '').($kh=='('?'(':'').$where.($kh==')'?')':''); return $this->get_class(); } // 设置exist子查询 function where_in_select($key, $sql, $split='AND', $kh = '') { $where = $key.' IN(' .$this->db->repace_table($sql).')'; $this->where .= ($this->where ? " $split " : '').($kh=='('?'(':'').$where.($kh==')'?')':''); return $this->get_class(); } // 设置group_by子句 function group_by($groups) { if(is_array($groups)) { foreach($groups as $key => $val) { $groups[$key] = $this->db->_ck_field($val); } $groupby = implode(',', $groups); } elseif(is_string($groups)) { $groupby = $this->db->_ck_field($groups); } $this->group_by .= ($this->group_by ? ',' : '').$groupby; return $this->get_class(); } //设置having子句 function having($exp) { $this->having = $exp; return $this->get_class(); } // 设置order_by子句 function order_by($field, $type='ASC') { if($field=='NULL') { $this->order_by = "NULL"; return $this->get_class(); } elseif(is_string($field)) { if(strpos($field, ' ')) { list($field, $type) = explode(' ', $field); } $type = strtoupper($type); $orderby = $this->db->_ck_field($field).($type=='DESC' ? (' '.$type) : ''); } elseif(is_array($field)) { $split = ''; foreach ($field as $key => $val) { $val = strtoupper($val); $orderby .= $split.$this->db->_ck_field($key).($val=='DESC' ? (' '.$val) : ''); $split = ','; } } $this->order_by .= ($this->order_by ? ',' : '').$orderby; return $this->get_class(); } // 设置 limit 子句 function limit($start, $offset) { $start = (int) $start; $offset = (int) $offset; if(!$start && !$offset) { return $this->get_class(); } if(!$start) { $this->limit = "$offset"; } if (!$offset) { $offset = 10; } $this->limit = "$start, $offset"; return $this->get_class(); } /** * SQL代码回滚,将在缓存的SQL重新设置成当前有效的SQL,支持回滚部分参数 * @param string $vars 需要回滚的表但是字段,例如from,where */ function sql_roll_back($vars = null) { $arr = $vars ? (is_array($vars) ? $vars : explode(',',$vars)) : $this->var_fields; foreach($arr as $v) { $n = 'cache_'.$v; $this->$v = $this->$n; } return $this->get_class(); } //组合一个查询sql function get_sql($get_count_sql = false) { foreach($this->var_fields as $v) { $$v = $v; } if(!$this->$from) show_error(lang('global_sql_invalid', "FROM(Get)")); $SQL = "SELECT ".($get_count_sql ? "COUNT(*)":($this->$select ? $this->$select : "*")) . " FROM ".$this->$from . ($this->$index ? " USE INDEX ".$this->index : "") . ($this->$where ? " WHERE ".$this->where : "") . ($this->$group_by ? " GROUP BY ".$this->$group_by : "") . ($this->$having ? " HAVING ".$this->$having : "") . ($this->$order_by ? " ORDER BY ".$this->$order_by : "") . ($get_count_sql ? '' : ($this->$limit ? " LIMIT ".$this->$limit : "")); return $SQL; } //组合一个插入sql function insert_sql($replace = FALSE, $update = FALSE) { foreach($this->var_fields as $v) { $$v = $v; } if(empty($this->$from)) { show_error(lang('global_sql_invalid', 'FROM(insert)')); } if(empty($this->$set)) { show_error(lang('global_sql_invalid', 'SET(insert)')); } $split = $setsql = ''; foreach($this->$set as $key => $val) { $setsql .= $split.$key.'='.$val; $split = ','; } if($update) { $SQL = "UPDATE ".$this->$from." SET ".$setsql. ($this->$where ? " WHERE ".$this->$where : "") . ($this->$order_by ? " ORDER BY ".$this->$order_by : ""); } else { $SQL = ($replace ? "REPLACE " : "INSERT ").$this->$from." SET ".$setsql; } return $SQL; } //组合成一个删除sql function delete_sql() { foreach($this->var_fields as $v) { $$v = $v; } if(!$this->$from) show_error(lang('global_sql_invalid', "FROM(delete)")); $SQL = "DELETE FROM ".$this->$from.($this->$where ? " WHERE ".$this->$where : ""); return $SQL; } /** * 清理当前的sql表达式内容 * @param string $name [description] */ function clear($name = 'ALL') { if($name == 'ALL') { foreach($this->var_fields as $v) { $this->$v = ''; } } elseif(isset($name[$this->var_fields])) { $this->$name = ''; } } /** * 特殊含义的sql解析 * * @param string $exp * @param string $value * @param string $split * @return string */ function _exp_where($exp,$value,$split) { $pattern_arr = array("/ union /i", "/ select /i", "/ update /i", "/ outfile /i"); $where = ''; switch($exp) { case 'sql': foreach($pattern_arr as $p) if(preg_match($p,$value)) return; $where = $value; break; } if(!$where) return; $this->where .= ($this->where ? " $split " : '').$where; } //缓存SQL各子句数据 function _cache_sql($clear=FALSE) { foreach($this->var_fields as $v) { $n = 'cache_'.$v; $this->$n = $this->$v; if($clear) $this->$v = ''; } } /** * 返回可用于函数链操作的类 * @return [type] [description] */ protected function get_class() { return $this->is_activerecord ? $this->db : $this; } } ~~~