From 76b7f02ea4fed4612815e8bf01ac2fe9c0215e11 Mon Sep 17 00:00:00 2001 From: thinkphp Date: Thu, 6 Oct 2016 19:48:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E8=BF=9Bjoin=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=92=8Calias=E6=96=B9=E6=B3=95=E7=9A=84=E8=A7=A3=E6=9E=90=20?= =?UTF-8?q?=E6=94=B9=E8=BF=9B=E8=BD=AF=E5=88=A0=E9=99=A4=E7=9A=84base?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/think/db/Builder.php | 73 ++++++++++++++++++----------- library/think/db/Query.php | 51 +++++++++++++++----- library/think/db/builder/Mysql.php | 11 ++++- library/think/db/builder/Pgsql.php | 11 ++++- library/think/db/builder/Sqlite.php | 21 +++++++++ library/think/db/builder/Sqlsrv.php | 14 +++++- library/traits/model/SoftDelete.php | 7 ++- 7 files changed, 140 insertions(+), 48 deletions(-) diff --git a/library/think/db/Builder.php b/library/think/db/Builder.php index 15a240ad..4f57c84a 100644 --- a/library/think/db/Builder.php +++ b/library/think/db/Builder.php @@ -89,7 +89,7 @@ abstract class Builder $result = []; foreach ($data as $key => $val) { - $item = $this->parseKey($key); + $item = $this->parseKey($key, $options); if (!in_array($key, $fields, true)) { if ($options['strict']) { throw new Exception('fields not exists:[' . $key . ']'); @@ -115,9 +115,10 @@ abstract class Builder * 字段名分析 * @access protected * @param string $key + * @param array $options * @return string */ - protected function parseKey($key) + protected function parseKey($key, $options = []) { return $key; } @@ -146,10 +147,11 @@ abstract class Builder /** * field分析 * @access protected - * @param mixed $fields + * @param mixed $fields + * @param array $options * @return string */ - protected function parseField($fields) + protected function parseField($fields, $options = []) { if ('*' == $fields || empty($fields)) { $fieldsStr = '*'; @@ -158,9 +160,9 @@ abstract class Builder $array = []; foreach ($fields as $key => $field) { if (!is_numeric($key)) { - $array[] = $this->parseKey($key) . ' AS ' . $this->parseKey($field); + $array[] = $this->parseKey($key, $options) . ' AS ' . $this->parseKey($field, $options); } else { - $array[] = $this->parseKey($field); + $array[] = $this->parseKey($field, $options); } } $fieldsStr = implode(',', $array); @@ -172,9 +174,10 @@ abstract class Builder * table分析 * @access protected * @param mixed $table + * @param array $options * @return string */ - protected function parseTable($tables) + protected function parseTable($tables, $options = []) { if (is_array($tables)) { // 支持别名定义 @@ -183,12 +186,16 @@ abstract class Builder $this->parseKey($table) . ' ' . $this->parseKey($alias) : $this->parseKey($alias); } - $tables = $array; + $tables = implode(',', $array); } elseif (is_string($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) { // 字段分析 - $key = $field ? $this->parseKey($field) : ''; + $key = $field ? $this->parseKey($field, $options) : ''; // 查询规则和条件 if (!is_array($val)) { @@ -425,14 +432,24 @@ abstract class Builder /** * join分析 * @access protected - * @param mixed $join + * @param array $join + * @param array $options 查询条件 * @return string */ - protected function parseJoin($join) + protected function parseJoin($join, $options = []) { $joinStr = ''; 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; } @@ -450,13 +467,13 @@ abstract class Builder foreach ($order as $key => $val) { if (is_numeric($key)) { if (false === strpos($val, '(')) { - $array[] = $this->parseKey($val); + $array[] = $this->parseKey($val, $options); } elseif ('[rand]' == $val) { $array[] = $this->parseRand(); } } else { $sort = in_array(strtolower(trim($val)), ['asc', 'desc']) ? ' ' . $val : ''; - $array[] = $this->parseKey($key) . ' ' . $sort; + $array[] = $this->parseKey($key, $options) . ' ' . $sort; } } $order = implode(',', $array); @@ -572,10 +589,10 @@ abstract class Builder $sql = str_replace( ['%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->parseField($options['field']), - $this->parseJoin($options['join']), + $this->parseField($options['field'], $options), + $this->parseJoin($options['join'], $options), $this->parseWhere($options['where'], $options), $this->parseGroup($options['group']), $this->parseHaving($options['having']), @@ -611,7 +628,7 @@ abstract class Builder ['%INSERT%', '%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'], [ $replace ? 'REPLACE' : 'INSERT', - $this->parseTable($options['table']), + $this->parseTable($options['table'], $options), implode(' , ', $fields), implode(' , ', $values), $this->parseComment($options['comment']), @@ -657,7 +674,7 @@ abstract class Builder $sql = str_replace( ['%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'], [ - $this->parseTable($options['table']), + $this->parseTable($options['table'], $options), implode(' , ', $fields), implode(' UNION ALL ', $values), $this->parseComment($options['comment']), @@ -681,7 +698,7 @@ abstract class Builder } $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; } @@ -694,7 +711,7 @@ abstract class Builder */ public function update($data, $options) { - $table = $this->parseTable($options['table']); + $table = $this->parseTable($options['table'], $options); $data = $this->parseData($data, $options); if (empty($data)) { return ''; @@ -706,9 +723,9 @@ abstract class Builder $sql = str_replace( ['%TABLE%', '%SET%', '%JOIN%', '%WHERE%', '%ORDER%', '%LIMIT%', '%LOCK%', '%COMMENT%'], [ - $this->parseTable($options['table']), + $this->parseTable($options['table'], $options), implode(',', $set), - $this->parseJoin($options['join']), + $this->parseJoin($options['join'], $options), $this->parseWhere($options['where'], $options), $this->parseOrder($options['order']), $this->parseLimit($options['limit']), @@ -730,9 +747,9 @@ abstract class Builder $sql = str_replace( ['%TABLE%', '%USING%', '%JOIN%', '%WHERE%', '%ORDER%', '%LIMIT%', '%LOCK%', '%COMMENT%'], [ - $this->parseTable($options['table']), - !empty($options['using']) ? ' USING ' . $this->parseTable($options['using']) . ' ' : '', - $this->parseJoin($options['join']), + $this->parseTable($options['table'], $options), + !empty($options['using']) ? ' USING ' . $this->parseTable($options['using'], $options) . ' ' : '', + $this->parseJoin($options['join'], $options), $this->parseWhere($options['where'], $options), $this->parseOrder($options['order']), $this->parseLimit($options['limit']), diff --git a/library/think/db/Query.php b/library/think/db/Query.php index 2e9308cc..1af39e58 100644 --- a/library/think/db/Query.php +++ b/library/think/db/Query.php @@ -668,7 +668,9 @@ class Query if (is_array($join)) { if (0 !== $key = key($join)) { // 设置了键名则键名为表名,键值作为表的别名 - $table = $key . ' ' . array_shift($join); + $table = $key; + $alias = array_shift($join); + $this->alias([$table => $alias]); } else { $table = array_shift($join); } @@ -689,11 +691,15 @@ class Query } else { $table = $join; } + if (strpos($table, ' ')) { + list($table, $alias) = explode(' ', $table); + $this->alias([$table => $alias]); + } } if (is_array($condition)) { $condition = implode(' AND ', $condition); } - $this->options['join'][] = strtoupper($type) . ' JOIN ' . $table . ' ON ' . $condition; + $this->options['join'][] = [$table, strtoupper($type), $condition]; } return $this; } @@ -1021,11 +1027,29 @@ class Query /** * 指定当前操作的数据表 * @access public - * @param string $table 表名 + * @param mixed $table 表名 * @return $this */ 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; return $this; } @@ -1145,12 +1169,20 @@ class Query /** * 指定数据表别名 * @access public - * @param string $alias 数据表别名 + * @param mixed $alias 数据表别名 * @return $this */ 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; } @@ -1630,8 +1662,8 @@ class Query { $pk = $this->getPk($options); // 获取当前数据表 - if (!empty($options['alias'])) { - $alias = $options['alias']; + if (!empty($options['alias'][$options['table']])) { + $alias = $options['alias'][$options['table']]; } if (is_string($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'])) { $options['field'] = '*'; } diff --git a/library/think/db/builder/Mysql.php b/library/think/db/builder/Mysql.php index 04586906..7744be9a 100644 --- a/library/think/db/builder/Mysql.php +++ b/library/think/db/builder/Mysql.php @@ -24,19 +24,28 @@ class Mysql extends Builder * 字段和表名处理 * @access protected * @param string $key + * @param array $options * @return string */ - protected function parseKey($key) + protected function parseKey($key, $options = []) { $key = trim($key); if (strpos($key, '$.') && false === strpos($key, '(')) { // JSON字段支持 list($field, $name) = explode('$.', $key); $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)) { $key = '`' . $key . '`'; } + if (isset($table)) { + $key = '`' . $table . '`.' . $key; + } return $key; } diff --git a/library/think/db/builder/Pgsql.php b/library/think/db/builder/Pgsql.php index 0a955a5b..e6e7dffa 100644 --- a/library/think/db/builder/Pgsql.php +++ b/library/think/db/builder/Pgsql.php @@ -43,15 +43,24 @@ class Pgsql extends Builder * 字段和表名处理 * @access protected * @param string $key + * @param array $options * @return string */ - protected function parseKey($key) + protected function parseKey($key, $options = []) { $key = trim($key); if (strpos($key, '$.') && false === strpos($key, '(')) { // JSON字段支持 list($field, $name) = explode('$.', $key); $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; } diff --git a/library/think/db/builder/Sqlite.php b/library/think/db/builder/Sqlite.php index 17e59cb2..c9f55027 100644 --- a/library/think/db/builder/Sqlite.php +++ b/library/think/db/builder/Sqlite.php @@ -48,4 +48,25 @@ class Sqlite extends Builder 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; + } } diff --git a/library/think/db/builder/Sqlsrv.php b/library/think/db/builder/Sqlsrv.php index bf630d90..3ef28f7c 100644 --- a/library/think/db/builder/Sqlsrv.php +++ b/library/think/db/builder/Sqlsrv.php @@ -61,17 +61,27 @@ class Sqlsrv extends Builder } /** - * 字段名分析 + * 字段和表名处理 * @access protected * @param string $key + * @param array $options * @return string */ - protected function parseKey($key) + 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 (!is_numeric($key) && !preg_match('/[,\'\"\*\(\)\[.\s]/', $key)) { $key = '[' . $key . ']'; } + if (isset($table)) { + $key = '[' . $table . '].' . $key; + } return $key; } diff --git a/library/traits/model/SoftDelete.php b/library/traits/model/SoftDelete.php index e08d96aa..4bb072dc 100644 --- a/library/traits/model/SoftDelete.php +++ b/library/traits/model/SoftDelete.php @@ -133,10 +133,9 @@ trait SoftDelete */ protected function getDeleteTimeField($read = false) { - if (isset($this->deleteTime)) { - $field = $this->deleteTime; - } else { - $field = 'delete_time'; + $field = isset($this->deleteTime) ? $this->deleteTime : 'delete_time'; + if (!strpos($field, '.')) { + $field = $this->db(false)->getTable() . '.' . $field; } if (!$read && strpos($field, '.')) { list($alias, $field) = explode('.', $field);