mirror of
https://gitee.com/ShopeX/OMS
synced 2026-03-23 02:45:33 +08:00
422 lines
11 KiB
PHP
422 lines
11 KiB
PHP
<?php
|
||
/**
|
||
* Copyright © ShopeX (http://www.shopex.cn). All rights reserved.
|
||
* See LICENSE file for license details.
|
||
*/
|
||
|
||
|
||
/*
|
||
* 实现个简单的select对像
|
||
* 目前只实现于core_db的select
|
||
* 只支持单表 2010/4/23 edwin.lzh@gmail.com
|
||
*/
|
||
|
||
class dbeav_select
|
||
{
|
||
|
||
const DISTINCT = 'distinct';
|
||
const COLUMNS = 'columns';
|
||
const FROM = 'from';
|
||
const WHERE = 'where';
|
||
const GROUP = 'group';
|
||
const HAVING = 'having';
|
||
const ORDER = 'order';
|
||
const LIMIT_COUNT = 'limit_count';
|
||
const LIMIT_OFFSET = 'limit_offset';
|
||
|
||
const SQL_WILDCARD = '*';
|
||
const SQL_SELECT = 'SELECT';
|
||
const SQL_FROM = 'FROM';
|
||
const SQL_WHERE = 'WHERE';
|
||
const SQL_DISTINCT = 'DISTINCT';
|
||
const SQL_GROUP_BY = 'GROUP BY';
|
||
const SQL_ORDER_BY = 'ORDER BY';
|
||
const SQL_HAVING = 'HAVING';
|
||
const SQL_AND = 'AND';
|
||
const SQL_AS = 'AS';
|
||
const SQL_OR = 'OR';
|
||
const SQL_ON = 'ON';
|
||
const SQL_ASC = 'ASC';
|
||
const SQL_DESC = 'DESC';
|
||
|
||
protected static $_init_parts = array(
|
||
self::DISTINCT => false,
|
||
self::COLUMNS => array(),
|
||
self::FROM => null,
|
||
self::WHERE => array(),
|
||
self::GROUP => array(),
|
||
self::HAVING => array(),
|
||
self::ORDER => array(),
|
||
self::LIMIT_COUNT => null,
|
||
self::LIMIT_OFFSET => null,
|
||
);
|
||
|
||
private $_parts = array();
|
||
|
||
/**
|
||
* 设置_model
|
||
* @param mixed $model model
|
||
* @return mixed 返回操作结果
|
||
*/
|
||
public function set_model(&$model)
|
||
{
|
||
$this->_model = $model;
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* 获取_model
|
||
* @return mixed 返回结果
|
||
*/
|
||
public function get_model()
|
||
{
|
||
return $this->_model;
|
||
}//End Function
|
||
|
||
/**
|
||
* 设置_adapter
|
||
* @param mixed $adapter adapter
|
||
* @return mixed 返回操作结果
|
||
*/
|
||
public function set_adapter($adapter)
|
||
{
|
||
$this->_adapter = $adapter;
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* 获取_parts
|
||
* @return mixed 返回结果
|
||
*/
|
||
public function get_parts()
|
||
{
|
||
return $this->_parts;
|
||
}//End Function
|
||
|
||
/**
|
||
* 重置
|
||
* @param mixed $part part
|
||
* @return mixed 返回值
|
||
*/
|
||
public function reset($part=null)
|
||
{
|
||
if ($part == null) {
|
||
$this->_parts = self::$_init_parts;
|
||
} else if (array_key_exists($part, self::$_init_parts)) {
|
||
$this->_parts[$part] = self::$_init_parts[$part];
|
||
}
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* distinct
|
||
* @param mixed $flag flag
|
||
* @return mixed 返回值
|
||
*/
|
||
public function distinct($flag=true)
|
||
{
|
||
$this->_parts[self::DISTINCT] = (bool) $flag;
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* from
|
||
* @param mixed $db db
|
||
* @param mixed $cols cols
|
||
* @return mixed 返回值
|
||
*/
|
||
public function from($db, $cols=self::SQL_WILDCARD)
|
||
{
|
||
$this->_parts[self::FROM] = $db;
|
||
$this->columns($cols);
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* columns
|
||
* @param mixed $cols cols
|
||
* @return mixed 返回值
|
||
*/
|
||
public function columns($cols=self::SQL_WILDCARD)
|
||
{
|
||
$this->reset('columns');
|
||
if (!is_array($cols)) $cols = array($cols);
|
||
foreach($cols AS $alias => $col){
|
||
$this->_parts[self::COLUMNS][] = array($col, is_string($alias) ? $alias : null);
|
||
}
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* where
|
||
* @param mixed $str str
|
||
* @param mixed $val val
|
||
* @return mixed 返回值
|
||
*/
|
||
public function where($str, $val='')
|
||
{
|
||
$this->_parts[self::WHERE][] = $this->_where($str, $val, true);
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* or_where
|
||
* @param mixed $str str
|
||
* @param mixed $val val
|
||
* @return mixed 返回值
|
||
*/
|
||
public function or_where($str, $val='')
|
||
{
|
||
$this->_parts[self::WHERE][] = $this->_where($str, $val, false);
|
||
return $this;
|
||
}//End Function
|
||
|
||
private function _where($str, $val, $bool)
|
||
{
|
||
$str = (isset($val)) ? $this->_adapter->quote_into($str, $val) : $str;
|
||
return ($bool) ? self::SQL_AND . ' ' . $str : self::SQL_OR . ' ' . $str;
|
||
}//End Function
|
||
|
||
/**
|
||
* group
|
||
* @param mixed $groups groups
|
||
* @return mixed 返回值
|
||
*/
|
||
public function group($groups)
|
||
{
|
||
if(!is_array($groups)) $groups = array($groups);
|
||
foreach($groups AS $group){
|
||
$this->_parts[self::GROUP][] = $group;
|
||
}
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* having
|
||
* @param mixed $str str
|
||
* @return mixed 返回值
|
||
*/
|
||
public function having($str)
|
||
{
|
||
if(func_num_args() > 1){
|
||
$str = $this->_adapter->quote_into($str, func_get_arg(1));
|
||
}
|
||
if ($this->_parts[self::HAVING]){
|
||
$this->_parts[self::HAVING][] = self::SQL_AND . " " . $str;
|
||
}else{
|
||
$this->_parts[self::HAVING][] = $str;
|
||
}
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* or_having
|
||
* @param mixed $str str
|
||
* @return mixed 返回值
|
||
*/
|
||
public function or_having($str)
|
||
{
|
||
if(func_num_args() > 1){
|
||
$str = $this->_adapter->quote_into($str, func_get_arg(1));
|
||
}
|
||
if ($this->_parts[self::HAVING]){
|
||
$this->_parts[self::HAVING][] = self::SQL_OR . " " . $str;
|
||
}else{
|
||
$this->_parts[self::HAVING][] = $str;
|
||
}
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* order
|
||
* @param mixed $orders orders
|
||
* @return mixed 返回值
|
||
*/
|
||
public function order($orders)
|
||
{
|
||
if(!is_array($orders)) $orders = array($orders);
|
||
|
||
foreach($orders AS $order){
|
||
$direction = self::SQL_ASC;
|
||
if (preg_match('/(.*\W)(' . self::SQL_ASC . '|' . self::SQL_DESC . ')\b/si', $order, $matches)) {
|
||
$val = trim($matches[1]);
|
||
$direction = strtoupper($matches[2]);
|
||
}
|
||
$this->_parts[self::ORDER][] = array($val, $direction);
|
||
}
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* limit
|
||
* @param mixed $offset offset
|
||
* @param mixed $count count
|
||
* @return mixed 返回值
|
||
*/
|
||
public function limit($offset=null, $count=null)
|
||
{
|
||
$this->_parts[self::LIMIT_COUNT] = (int) $count;
|
||
$this->_parts[self::LIMIT_OFFSET] = (int) $offset;
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* page
|
||
* @param mixed $page page
|
||
* @param mixed $size size
|
||
* @return mixed 返回值
|
||
*/
|
||
public function page($page=null, $size=null)
|
||
{
|
||
$page = ($page > 0) ? $page : 1;
|
||
$size = ($size > 0) ? $size : 1;
|
||
$this->_parts[self::LIMIT_COUNT] = (int) $size;
|
||
$this->_parts[self::LIMIT_OFFSET] = (int) $size * ($page - 1);
|
||
return $this;
|
||
}//End Function
|
||
|
||
/**
|
||
* instance
|
||
* @return mixed 返回值
|
||
*/
|
||
public function instance()
|
||
{
|
||
$this->_adapter->set_obj($this);
|
||
return $this->_adapter;
|
||
}//End Function
|
||
|
||
/**
|
||
* assemble
|
||
* @return mixed 返回值
|
||
*/
|
||
public function assemble()
|
||
{
|
||
$sql = self::SQL_SELECT;
|
||
foreach (array_keys(self::$_init_parts) as $part) {
|
||
$part = strtolower($part);
|
||
if($part == 'limit_count') continue; //todo:减少判断methon_exists提高性能
|
||
$method = 'render_' . $part;
|
||
//if (method_exists($this, $method)) {
|
||
$sql = $this->$method($sql);
|
||
//}
|
||
}
|
||
return $sql;
|
||
}//End Function
|
||
|
||
protected function render_distinct($sql)
|
||
{
|
||
if ($this->_parts[self::DISTINCT]) {
|
||
$sql .= ' ' . self::SQL_DISTINCT;
|
||
}
|
||
return $sql;
|
||
}//End Function
|
||
|
||
protected function render_columns($sql)
|
||
{
|
||
if(!count($this->_parts[self::COLUMNS])){
|
||
return null;
|
||
}
|
||
$columns = array();
|
||
foreach ($this->_parts[self::COLUMNS] as $columnEntry) {
|
||
list($column, $alias) = $columnEntry;
|
||
$columns[] = $this->_adapter->quote_column_as($column, $alias);
|
||
}
|
||
return $sql .= ' ' . implode(', ', $columns);
|
||
}//End Function
|
||
|
||
/**
|
||
* 获取_columns
|
||
* @return mixed 返回结果
|
||
*/
|
||
public function get_columns()
|
||
{
|
||
$columns = array();
|
||
if(count($this->_parts[self::COLUMNS])){
|
||
foreach ($this->_parts[self::COLUMNS] as $columnEntry) {
|
||
list($column, $alias) = $columnEntry;
|
||
$columns[] = $this->_adapter->quote_column_as($column, $alias);
|
||
}
|
||
}
|
||
return $columns;
|
||
}//End Function
|
||
|
||
protected function render_from($sql)
|
||
{
|
||
if(!empty($this->_parts[self::FROM])){
|
||
$sql .= ' ' . self::SQL_FROM . ' ' . $this->_adapter->quote_identifier($this->_parts[self::FROM]);
|
||
}
|
||
return $sql;
|
||
}//End Function
|
||
|
||
protected function render_where($sql)
|
||
{
|
||
if($this->_parts[self::FROM] && $this->_parts[self::WHERE]){
|
||
$sql .= ' ' . self::SQL_WHERE . ' 1=1 ' . implode(' ', $this->_parts[self::WHERE]);
|
||
}
|
||
return $sql;
|
||
}//End Function
|
||
|
||
protected function render_group($sql)
|
||
{
|
||
if($this->_parts[self::FROM] && $this->_parts[self::GROUP]){
|
||
$group = array();
|
||
foreach($this->_parts[self::GROUP] as $term){
|
||
$group[] = $this->_adapter->quote_identifier($term);
|
||
}
|
||
$sql .= ' ' . self::SQL_GROUP_BY . ' ' . implode(",\n\t", $group);
|
||
}
|
||
return $sql;
|
||
}//End Function
|
||
|
||
protected function render_having($sql)
|
||
{
|
||
if($this->_parts[self::FROM] && $this->_parts[self::HAVING]){
|
||
$sql .= ' ' . self::SQL_HAVING . ' ' . implode(' ', $this->_parts[self::HAVING]);
|
||
}
|
||
return $sql;
|
||
}//End Function
|
||
|
||
protected function render_order($sql)
|
||
{
|
||
if($this->_parts[self::ORDER]){
|
||
$order = array();
|
||
foreach($this->_parts[self::ORDER] as $term){
|
||
if (is_array($term)) {
|
||
$order[] = $this->_adapter->quote_identifier($term[0]) . ' ' . $term[1];
|
||
} else {
|
||
$order[] = $this->_adapter->quote_identifier($term);
|
||
}
|
||
}
|
||
$sql .= ' ' . self::SQL_ORDER_BY . ' ' . implode(', ', $order);
|
||
}
|
||
return $sql;
|
||
}//End Function
|
||
|
||
protected function render_limit_offset($sql)
|
||
{
|
||
$count = 0;
|
||
$offset = 0;
|
||
if(!empty($this->_parts[self::LIMIT_OFFSET])){
|
||
$offset = (int) $this->_parts[self::LIMIT_OFFSET];
|
||
$count = intval(9223372036854775807); //php最大值
|
||
}
|
||
if(!empty($this->_parts[self::LIMIT_COUNT])){
|
||
$count = (int) $this->_parts[self::LIMIT_COUNT];
|
||
}
|
||
if($count > 0){
|
||
$sql = trim($this->_adapter->limit($sql, $count, $offset));
|
||
}
|
||
return $sql;
|
||
}//End Function
|
||
|
||
/**
|
||
* to_sql
|
||
* @return mixed 返回值
|
||
*/
|
||
public function to_sql()
|
||
{
|
||
return $this->assemble();
|
||
}//End Function
|
||
|
||
}//End Class
|