改进join方法和alias方法的解析 改进软删除的base方法

This commit is contained in:
thinkphp
2016-10-06 19:48:11 +08:00
parent ebc015d620
commit 76b7f02ea4
7 changed files with 140 additions and 48 deletions

View File

@@ -89,7 +89,7 @@ abstract class Builder
$result = []; $result = [];
foreach ($data as $key => $val) { foreach ($data as $key => $val) {
$item = $this->parseKey($key); $item = $this->parseKey($key, $options);
if (!in_array($key, $fields, true)) { if (!in_array($key, $fields, true)) {
if ($options['strict']) { if ($options['strict']) {
throw new Exception('fields not exists:[' . $key . ']'); throw new Exception('fields not exists:[' . $key . ']');
@@ -115,9 +115,10 @@ abstract class Builder
* 字段名分析 * 字段名分析
* @access protected * @access protected
* @param string $key * @param string $key
* @param array $options
* @return string * @return string
*/ */
protected function parseKey($key) protected function parseKey($key, $options = [])
{ {
return $key; return $key;
} }
@@ -146,10 +147,11 @@ abstract class Builder
/** /**
* field分析 * field分析
* @access protected * @access protected
* @param mixed $fields * @param mixed $fields
* @param array $options
* @return string * @return string
*/ */
protected function parseField($fields) protected function parseField($fields, $options = [])
{ {
if ('*' == $fields || empty($fields)) { if ('*' == $fields || empty($fields)) {
$fieldsStr = '*'; $fieldsStr = '*';
@@ -158,9 +160,9 @@ abstract class Builder
$array = []; $array = [];
foreach ($fields as $key => $field) { foreach ($fields as $key => $field) {
if (!is_numeric($key)) { if (!is_numeric($key)) {
$array[] = $this->parseKey($key) . ' AS ' . $this->parseKey($field); $array[] = $this->parseKey($key, $options) . ' AS ' . $this->parseKey($field, $options);
} else { } else {
$array[] = $this->parseKey($field); $array[] = $this->parseKey($field, $options);
} }
} }
$fieldsStr = implode(',', $array); $fieldsStr = implode(',', $array);
@@ -172,9 +174,10 @@ abstract class Builder
* table分析 * table分析
* @access protected * @access protected
* @param mixed $table * @param mixed $table
* @param array $options
* @return string * @return string
*/ */
protected function parseTable($tables) protected function parseTable($tables, $options = [])
{ {
if (is_array($tables)) { if (is_array($tables)) {
// 支持别名定义 // 支持别名定义
@@ -183,12 +186,16 @@ abstract class Builder
$this->parseKey($table) . ' ' . $this->parseKey($alias) : $this->parseKey($table) . ' ' . $this->parseKey($alias) :
$this->parseKey($alias); $this->parseKey($alias);
} }
$tables = $array; $tables = implode(',', $array);
} elseif (is_string($tables)) { } elseif (is_string($tables)) {
$tables = $this->parseSqlTable($tables); $tables = $this->parseSqlTable($tables);
$tables = array_map([$this, 'parseKey'], explode(',', $tables)); if (isset($options['alias'][$tables])) {
$tables = $this->parseKey($tables) . ' ' . $this->parseKey($options['alias'][$tables]);
} else {
$tables = $this->parseKey($tables);
}
} }
return implode(',', $tables); return $tables;
} }
/** /**
@@ -263,7 +270,7 @@ abstract class Builder
protected function parseWhereItem($field, $val, $rule = '', $options = [], $binds = [], $bindName = null) protected function parseWhereItem($field, $val, $rule = '', $options = [], $binds = [], $bindName = null)
{ {
// 字段分析 // 字段分析
$key = $field ? $this->parseKey($field) : ''; $key = $field ? $this->parseKey($field, $options) : '';
// 查询规则和条件 // 查询规则和条件
if (!is_array($val)) { if (!is_array($val)) {
@@ -425,14 +432,24 @@ abstract class Builder
/** /**
* join分析 * join分析
* @access protected * @access protected
* @param mixed $join * @param array $join
* @param array $options 查询条件
* @return string * @return string
*/ */
protected function parseJoin($join) protected function parseJoin($join, $options = [])
{ {
$joinStr = ''; $joinStr = '';
if (!empty($join)) { if (!empty($join)) {
$joinStr = ' ' . implode(' ', $join) . ' '; foreach ($join as $item) {
list($table, $type, $on) = $item;
if (!empty($options['alias'])) {
foreach ($options['alias'] as $key => $val) {
$on = str_replace($key . '.', $this->parseKey($val, $options) . '.', $on);
}
}
$table = $this->parseTable($table, $options);
$joinStr .= ' ' . $type . ' JOIN ' . $table . ' ON ' . $on;
}
} }
return $joinStr; return $joinStr;
} }
@@ -450,13 +467,13 @@ abstract class Builder
foreach ($order as $key => $val) { foreach ($order as $key => $val) {
if (is_numeric($key)) { if (is_numeric($key)) {
if (false === strpos($val, '(')) { if (false === strpos($val, '(')) {
$array[] = $this->parseKey($val); $array[] = $this->parseKey($val, $options);
} elseif ('[rand]' == $val) { } elseif ('[rand]' == $val) {
$array[] = $this->parseRand(); $array[] = $this->parseRand();
} }
} else { } else {
$sort = in_array(strtolower(trim($val)), ['asc', 'desc']) ? ' ' . $val : ''; $sort = in_array(strtolower(trim($val)), ['asc', 'desc']) ? ' ' . $val : '';
$array[] = $this->parseKey($key) . ' ' . $sort; $array[] = $this->parseKey($key, $options) . ' ' . $sort;
} }
} }
$order = implode(',', $array); $order = implode(',', $array);
@@ -572,10 +589,10 @@ abstract class Builder
$sql = str_replace( $sql = str_replace(
['%TABLE%', '%DISTINCT%', '%FIELD%', '%JOIN%', '%WHERE%', '%GROUP%', '%HAVING%', '%ORDER%', '%LIMIT%', '%UNION%', '%LOCK%', '%COMMENT%', '%FORCE%'], ['%TABLE%', '%DISTINCT%', '%FIELD%', '%JOIN%', '%WHERE%', '%GROUP%', '%HAVING%', '%ORDER%', '%LIMIT%', '%UNION%', '%LOCK%', '%COMMENT%', '%FORCE%'],
[ [
$this->parseTable($options['table']), $this->parseTable($options['table'], $options),
$this->parseDistinct($options['distinct']), $this->parseDistinct($options['distinct']),
$this->parseField($options['field']), $this->parseField($options['field'], $options),
$this->parseJoin($options['join']), $this->parseJoin($options['join'], $options),
$this->parseWhere($options['where'], $options), $this->parseWhere($options['where'], $options),
$this->parseGroup($options['group']), $this->parseGroup($options['group']),
$this->parseHaving($options['having']), $this->parseHaving($options['having']),
@@ -611,7 +628,7 @@ abstract class Builder
['%INSERT%', '%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'], ['%INSERT%', '%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'],
[ [
$replace ? 'REPLACE' : 'INSERT', $replace ? 'REPLACE' : 'INSERT',
$this->parseTable($options['table']), $this->parseTable($options['table'], $options),
implode(' , ', $fields), implode(' , ', $fields),
implode(' , ', $values), implode(' , ', $values),
$this->parseComment($options['comment']), $this->parseComment($options['comment']),
@@ -657,7 +674,7 @@ abstract class Builder
$sql = str_replace( $sql = str_replace(
['%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'], ['%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'],
[ [
$this->parseTable($options['table']), $this->parseTable($options['table'], $options),
implode(' , ', $fields), implode(' , ', $fields),
implode(' UNION ALL ', $values), implode(' UNION ALL ', $values),
$this->parseComment($options['comment']), $this->parseComment($options['comment']),
@@ -681,7 +698,7 @@ abstract class Builder
} }
$fields = array_map([$this, 'parseKey'], $fields); $fields = array_map([$this, 'parseKey'], $fields);
$sql = 'INSERT INTO ' . $this->parseTable($table) . ' (' . implode(',', $fields) . ') ' . $this->select($options); $sql = 'INSERT INTO ' . $this->parseTable($table, $options) . ' (' . implode(',', $fields) . ') ' . $this->select($options);
return $sql; return $sql;
} }
@@ -694,7 +711,7 @@ abstract class Builder
*/ */
public function update($data, $options) public function update($data, $options)
{ {
$table = $this->parseTable($options['table']); $table = $this->parseTable($options['table'], $options);
$data = $this->parseData($data, $options); $data = $this->parseData($data, $options);
if (empty($data)) { if (empty($data)) {
return ''; return '';
@@ -706,9 +723,9 @@ abstract class Builder
$sql = str_replace( $sql = str_replace(
['%TABLE%', '%SET%', '%JOIN%', '%WHERE%', '%ORDER%', '%LIMIT%', '%LOCK%', '%COMMENT%'], ['%TABLE%', '%SET%', '%JOIN%', '%WHERE%', '%ORDER%', '%LIMIT%', '%LOCK%', '%COMMENT%'],
[ [
$this->parseTable($options['table']), $this->parseTable($options['table'], $options),
implode(',', $set), implode(',', $set),
$this->parseJoin($options['join']), $this->parseJoin($options['join'], $options),
$this->parseWhere($options['where'], $options), $this->parseWhere($options['where'], $options),
$this->parseOrder($options['order']), $this->parseOrder($options['order']),
$this->parseLimit($options['limit']), $this->parseLimit($options['limit']),
@@ -730,9 +747,9 @@ abstract class Builder
$sql = str_replace( $sql = str_replace(
['%TABLE%', '%USING%', '%JOIN%', '%WHERE%', '%ORDER%', '%LIMIT%', '%LOCK%', '%COMMENT%'], ['%TABLE%', '%USING%', '%JOIN%', '%WHERE%', '%ORDER%', '%LIMIT%', '%LOCK%', '%COMMENT%'],
[ [
$this->parseTable($options['table']), $this->parseTable($options['table'], $options),
!empty($options['using']) ? ' USING ' . $this->parseTable($options['using']) . ' ' : '', !empty($options['using']) ? ' USING ' . $this->parseTable($options['using'], $options) . ' ' : '',
$this->parseJoin($options['join']), $this->parseJoin($options['join'], $options),
$this->parseWhere($options['where'], $options), $this->parseWhere($options['where'], $options),
$this->parseOrder($options['order']), $this->parseOrder($options['order']),
$this->parseLimit($options['limit']), $this->parseLimit($options['limit']),

View File

@@ -668,7 +668,9 @@ class Query
if (is_array($join)) { if (is_array($join)) {
if (0 !== $key = key($join)) { if (0 !== $key = key($join)) {
// 设置了键名则键名为表名,键值作为表的别名 // 设置了键名则键名为表名,键值作为表的别名
$table = $key . ' ' . array_shift($join); $table = $key;
$alias = array_shift($join);
$this->alias([$table => $alias]);
} else { } else {
$table = array_shift($join); $table = array_shift($join);
} }
@@ -689,11 +691,15 @@ class Query
} else { } else {
$table = $join; $table = $join;
} }
if (strpos($table, ' ')) {
list($table, $alias) = explode(' ', $table);
$this->alias([$table => $alias]);
}
} }
if (is_array($condition)) { if (is_array($condition)) {
$condition = implode(' AND ', $condition); $condition = implode(' AND ', $condition);
} }
$this->options['join'][] = strtoupper($type) . ' JOIN ' . $table . ' ON ' . $condition; $this->options['join'][] = [$table, strtoupper($type), $condition];
} }
return $this; return $this;
} }
@@ -1021,11 +1027,29 @@ class Query
/** /**
* 指定当前操作的数据表 * 指定当前操作的数据表
* @access public * @access public
* @param string $table 表名 * @param mixed $table 表名
* @return $this * @return $this
*/ */
public function table($table) public function table($table)
{ {
if (is_string($table)) {
if (strpos($table, ',')) {
$tables = explode(',', $table);
$table = [];
foreach ($tables as $item) {
list($item, $alias) = explode(' ', trim($item));
if ($alias) {
$this->alias([$item => $alias]);
$table[$item] = $alias;
} else {
$table[] = $item;
}
}
} elseif (strpos($table, ' ')) {
list($table, $alias) = explode(' ', $table);
$this->alias([$table => $alias]);
}
}
$this->options['table'] = $table; $this->options['table'] = $table;
return $this; return $this;
} }
@@ -1145,12 +1169,20 @@ class Query
/** /**
* 指定数据表别名 * 指定数据表别名
* @access public * @access public
* @param string $alias 数据表别名 * @param mixed $alias 数据表别名
* @return $this * @return $this
*/ */
public function alias($alias) public function alias($alias)
{ {
$this->options['alias'] = $alias; if (is_array($alias)) {
foreach ($alias as $key => $val) {
$this->options['alias'][$key] = $val;
}
} else {
$table = isset($this->options['table']) ? $this->options['table'] : $this->getTable();
$this->options['alias'][$table] = $alias;
}
return $this; return $this;
} }
@@ -1630,8 +1662,8 @@ class Query
{ {
$pk = $this->getPk($options); $pk = $this->getPk($options);
// 获取当前数据表 // 获取当前数据表
if (!empty($options['alias'])) { if (!empty($options['alias'][$options['table']])) {
$alias = $options['alias']; $alias = $options['alias'][$options['table']];
} }
if (is_string($pk)) { if (is_string($pk)) {
$key = isset($alias) ? $alias . '.' . $pk : $pk; $key = isset($alias) ? $alias . '.' . $pk : $pk;
@@ -2201,11 +2233,6 @@ class Query
} }
} }
// 表别名
if (!empty($options['alias'])) {
$options['table'] .= ' ' . $options['alias'];
}
if (!isset($options['field'])) { if (!isset($options['field'])) {
$options['field'] = '*'; $options['field'] = '*';
} }

View File

@@ -24,19 +24,28 @@ class Mysql extends Builder
* 字段和表名处理 * 字段和表名处理
* @access protected * @access protected
* @param string $key * @param string $key
* @param array $options
* @return string * @return string
*/ */
protected function parseKey($key) protected function parseKey($key, $options = [])
{ {
$key = trim($key); $key = trim($key);
if (strpos($key, '$.') && false === strpos($key, '(')) { if (strpos($key, '$.') && false === strpos($key, '(')) {
// JSON字段支持 // JSON字段支持
list($field, $name) = explode('$.', $key); list($field, $name) = explode('$.', $key);
$key = 'json_extract(' . $field . ', \'$.' . $name . '\')'; $key = 'json_extract(' . $field . ', \'$.' . $name . '\')';
} elseif (strpos($key, '.')) {
list($table, $key) = explode('.', $key, 2);
if (isset($options['alias'][$table])) {
$table = $options['alias'][$table];
}
} }
if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) { if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) {
$key = '`' . $key . '`'; $key = '`' . $key . '`';
} }
if (isset($table)) {
$key = '`' . $table . '`.' . $key;
}
return $key; return $key;
} }

View File

@@ -43,15 +43,24 @@ class Pgsql extends Builder
* 字段和表名处理 * 字段和表名处理
* @access protected * @access protected
* @param string $key * @param string $key
* @param array $options
* @return string * @return string
*/ */
protected function parseKey($key) protected function parseKey($key, $options = [])
{ {
$key = trim($key); $key = trim($key);
if (strpos($key, '$.') && false === strpos($key, '(')) { if (strpos($key, '$.') && false === strpos($key, '(')) {
// JSON字段支持 // JSON字段支持
list($field, $name) = explode('$.', $key); list($field, $name) = explode('$.', $key);
$key = $field . '->>\'' . $name . '\''; $key = $field . '->>\'' . $name . '\'';
} elseif (strpos($key, '.')) {
list($table, $key) = explode('.', $key, 2);
if (isset($options['alias'][$table])) {
$table = $options['alias'][$table];
}
}
if (isset($table)) {
$key = $table . '.' . $key;
} }
return $key; return $key;
} }

View File

@@ -48,4 +48,25 @@ class Sqlite extends Builder
return 'RANDOM()'; return 'RANDOM()';
} }
/**
* 字段和表名处理
* @access protected
* @param string $key
* @param array $options
* @return string
*/
protected function parseKey($key, $options = [])
{
$key = trim($key);
if (strpos($key, '.')) {
list($table, $key) = explode('.', $key, 2);
if (isset($options['alias'][$table])) {
$table = $options['alias'][$table];
}
}
if (isset($table)) {
$key = $table . '.' . $key;
}
return $key;
}
} }

View File

@@ -61,17 +61,27 @@ class Sqlsrv extends Builder
} }
/** /**
* 字段名分析 * 字段和表名处理
* @access protected * @access protected
* @param string $key * @param string $key
* @param array $options
* @return string * @return string
*/ */
protected function parseKey($key) protected function parseKey($key, $options = [])
{ {
$key = trim($key); $key = trim($key);
if (strpos($key, '.')) {
list($table, $key) = explode('.', $key, 2);
if (isset($options['alias'][$table])) {
$table = $options['alias'][$table];
}
}
if (!is_numeric($key) && !preg_match('/[,\'\"\*\(\)\[.\s]/', $key)) { if (!is_numeric($key) && !preg_match('/[,\'\"\*\(\)\[.\s]/', $key)) {
$key = '[' . $key . ']'; $key = '[' . $key . ']';
} }
if (isset($table)) {
$key = '[' . $table . '].' . $key;
}
return $key; return $key;
} }

View File

@@ -133,10 +133,9 @@ trait SoftDelete
*/ */
protected function getDeleteTimeField($read = false) protected function getDeleteTimeField($read = false)
{ {
if (isset($this->deleteTime)) { $field = isset($this->deleteTime) ? $this->deleteTime : 'delete_time';
$field = $this->deleteTime; if (!strpos($field, '.')) {
} else { $field = $this->db(false)->getTable() . '.' . $field;
$field = 'delete_time';
} }
if (!$read && strpos($field, '.')) { if (!$read && strpos($field, '.')) {
list($alias, $field) = explode('.', $field); list($alias, $field) = explode('.', $field);