mirror of
https://gitee.com/fastadminnet/framework.git
synced 2026-07-07 15:12:48 +08:00
增加Expression类及相关方法
This commit is contained in:
@@ -1093,7 +1093,7 @@ class Request
|
|||||||
public function filterExp(&$value)
|
public function filterExp(&$value)
|
||||||
{
|
{
|
||||||
// 过滤查询特殊字符
|
// 过滤查询特殊字符
|
||||||
if (is_string($value) && preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT LIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i', $value)) {
|
if (is_string($value) && preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT LIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOT EXISTS|NOTEXISTS|EXISTS|NOT NULL|NOTNULL|NULL|BETWEEN TIME|NOT BETWEEN TIME|NOTBETWEEN TIME|NOTIN|NOT IN|IN)$/i', $value)) {
|
||||||
$value .= ' ';
|
$value .= ' ';
|
||||||
}
|
}
|
||||||
// TODO 其他安全过滤
|
// TODO 其他安全过滤
|
||||||
|
|||||||
@@ -99,8 +99,11 @@ abstract class Builder
|
|||||||
|
|
||||||
$result = [];
|
$result = [];
|
||||||
foreach ($data as $key => $val) {
|
foreach ($data as $key => $val) {
|
||||||
$item = $this->parseKey($key, $options);
|
$item = $this->parseKey($key, $options, true);
|
||||||
if (is_object($val) && method_exists($val, '__toString')) {
|
if ($val instanceof Expression) {
|
||||||
|
$result[$item] = $val->getValue();
|
||||||
|
continue;
|
||||||
|
} elseif (is_object($val) && method_exists($val, '__toString')) {
|
||||||
// 对象数据写入
|
// 对象数据写入
|
||||||
$val = $val->__toString();
|
$val = $val->__toString();
|
||||||
}
|
}
|
||||||
@@ -143,7 +146,7 @@ abstract class Builder
|
|||||||
* @param array $options
|
* @param array $options
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function parseKey($key, $options = [])
|
protected function parseKey($key, $options = [], $strict = false)
|
||||||
{
|
{
|
||||||
return $key;
|
return $key;
|
||||||
}
|
}
|
||||||
@@ -184,10 +187,12 @@ abstract class Builder
|
|||||||
// 支持 'field1'=>'field2' 这样的字段别名定义
|
// 支持 'field1'=>'field2' 这样的字段别名定义
|
||||||
$array = [];
|
$array = [];
|
||||||
foreach ($fields as $key => $field) {
|
foreach ($fields as $key => $field) {
|
||||||
if (!is_numeric($key)) {
|
if ($field instanceof Expression) {
|
||||||
$array[] = $this->parseKey($key, $options) . ' AS ' . $this->parseKey($field, $options);
|
$array[] = $field->getValue();
|
||||||
|
} elseif (!is_numeric($key)) {
|
||||||
|
$array[] = $this->parseKey($key, $options) . ' AS ' . $this->parseKey($field, $options, true);
|
||||||
} else {
|
} else {
|
||||||
$array[] = $this->parseKey($field, $options);
|
$array[] = $this->parseKey($field, $options, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$fieldsStr = implode(',', $array);
|
$fieldsStr = implode(',', $array);
|
||||||
@@ -264,6 +269,10 @@ abstract class Builder
|
|||||||
foreach ($where as $key => $val) {
|
foreach ($where as $key => $val) {
|
||||||
$str = [];
|
$str = [];
|
||||||
foreach ($val as $field => $value) {
|
foreach ($val as $field => $value) {
|
||||||
|
if ($value instanceof Expression) {
|
||||||
|
$str[] = ' ' . $logic . ' ( ' . $value->getValue() . ' )';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if ($value instanceof \Closure) {
|
if ($value instanceof \Closure) {
|
||||||
// 使用闭包查询
|
// 使用闭包查询
|
||||||
$query = new Query($this->connection);
|
$query = new Query($this->connection);
|
||||||
@@ -305,7 +314,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, $options) : '';
|
$key = $field ? $this->parseKey($field, $options, true) : '';
|
||||||
|
|
||||||
// 查询规则和条件
|
// 查询规则和条件
|
||||||
if (!is_array($val)) {
|
if (!is_array($val)) {
|
||||||
@@ -344,7 +353,9 @@ abstract class Builder
|
|||||||
$bindName = md5($bindName);
|
$bindName = md5($bindName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_object($value) && method_exists($value, '__toString')) {
|
if ($value instanceof Expression) {
|
||||||
|
|
||||||
|
} elseif (is_object($value) && method_exists($value, '__toString')) {
|
||||||
// 对象数据写入
|
// 对象数据写入
|
||||||
$value = $value->__toString();
|
$value = $value->__toString();
|
||||||
}
|
}
|
||||||
@@ -556,7 +567,9 @@ abstract class Builder
|
|||||||
if (is_array($order)) {
|
if (is_array($order)) {
|
||||||
$array = [];
|
$array = [];
|
||||||
foreach ($order as $key => $val) {
|
foreach ($order as $key => $val) {
|
||||||
if (is_numeric($key)) {
|
if ($val instanceof Expression) {
|
||||||
|
$array[] = $val->getValue();
|
||||||
|
} elseif (is_numeric($key)) {
|
||||||
if ('[rand]' == $val) {
|
if ('[rand]' == $val) {
|
||||||
if (method_exists($this, 'parseRand')) {
|
if (method_exists($this, 'parseRand')) {
|
||||||
$array[] = $this->parseRand();
|
$array[] = $this->parseRand();
|
||||||
|
|||||||
48
library/think/db/Expression.php
Normal file
48
library/think/db/Expression.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think\db;
|
||||||
|
|
||||||
|
class Expression
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 查询表达式
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建一个查询表达式
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($value)
|
||||||
|
{
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取表达式
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getValue()
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return (string) $this->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -800,6 +800,24 @@ class Query
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表达式方式指定查询字段
|
||||||
|
* @access public
|
||||||
|
* @param string $field 字段名
|
||||||
|
* @param array $bind 参数绑定
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function fieldRaw($field, array $bind = [])
|
||||||
|
{
|
||||||
|
$this->options['field'][] = $this->raw($field);
|
||||||
|
|
||||||
|
if ($bind) {
|
||||||
|
$this->bind($bind);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置数据
|
* 设置数据
|
||||||
* @access public
|
* @access public
|
||||||
@@ -862,6 +880,17 @@ class Query
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用表达式设置数据
|
||||||
|
* @access public
|
||||||
|
* @param mixed $value 表达式
|
||||||
|
* @return Expression
|
||||||
|
*/
|
||||||
|
public function raw($value)
|
||||||
|
{
|
||||||
|
return new Expression($value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指定JOIN查询字段
|
* 指定JOIN查询字段
|
||||||
* @access public
|
* @access public
|
||||||
@@ -975,6 +1004,37 @@ class Query
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定表达式查询条件
|
||||||
|
* @access public
|
||||||
|
* @param string $where 查询条件
|
||||||
|
* @param array $bind 参数绑定
|
||||||
|
* @param string $logic 查询逻辑 and or xor
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function whereRaw($where, $bind = [], $logic = 'AND')
|
||||||
|
{
|
||||||
|
$this->options['where'][$logic][] = $this->raw($where);
|
||||||
|
|
||||||
|
if ($bind) {
|
||||||
|
$this->bind($bind);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定表达式查询条件 OR
|
||||||
|
* @access public
|
||||||
|
* @param string $where 查询条件
|
||||||
|
* @param array $bind 参数绑定
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function whereOrRaw($where, $bind = [])
|
||||||
|
{
|
||||||
|
return $this->whereRaw($where, $bind, 'OR');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指定Null查询条件
|
* 指定Null查询条件
|
||||||
* @access public
|
* @access public
|
||||||
@@ -1163,7 +1223,9 @@ class Query
|
|||||||
$field = $this->options['via'] . '.' . $field;
|
$field = $this->options['via'] . '.' . $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($strict) {
|
if ($field instanceof Expression) {
|
||||||
|
return $this->whereRaw($field, is_array($op) ? $op : []);
|
||||||
|
} elseif ($strict) {
|
||||||
// 使用严格模式查询
|
// 使用严格模式查询
|
||||||
$where[$field] = [$op, $condition];
|
$where[$field] = [$op, $condition];
|
||||||
|
|
||||||
@@ -1451,6 +1513,24 @@ class Query
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表达式方式指定Field排序
|
||||||
|
* @access public
|
||||||
|
* @param string $field 排序字段
|
||||||
|
* @param array $bind 参数绑定
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function orderRaw($field, array $bind = [])
|
||||||
|
{
|
||||||
|
$this->options['order'][] = $this->raw($field);
|
||||||
|
|
||||||
|
if ($bind) {
|
||||||
|
$this->bind($bind);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询缓存
|
* 查询缓存
|
||||||
* @access public
|
* @access public
|
||||||
|
|||||||
@@ -86,13 +86,16 @@ class Mysql extends Builder
|
|||||||
* @param array $options
|
* @param array $options
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function parseKey($key, $options = [])
|
protected function parseKey($key, $options = [], $strict = false)
|
||||||
{
|
{
|
||||||
|
if (is_int($key)) {
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
$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 . '\')';
|
return 'json_extract(' . $field . ', \'$.' . $name . '\')';
|
||||||
} elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) {
|
} elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) {
|
||||||
list($table, $key) = explode('.', $key, 2);
|
list($table, $key) = explode('.', $key, 2);
|
||||||
if ('__TABLE__' == $table) {
|
if ('__TABLE__' == $table) {
|
||||||
@@ -102,7 +105,7 @@ class Mysql extends Builder
|
|||||||
$table = $options['alias'][$table];
|
$table = $options['alias'][$table];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) {
|
if ($strict || !preg_match('/[,\'\"\*\(\)`.\s]/', $key)) {
|
||||||
$key = '`' . $key . '`';
|
$key = '`' . $key . '`';
|
||||||
}
|
}
|
||||||
if (isset($table)) {
|
if (isset($table)) {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class Pgsql extends Builder
|
|||||||
* @param array $options
|
* @param array $options
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function parseKey($key, $options = [])
|
protected function parseKey($key, $options = [], $strict = false)
|
||||||
{
|
{
|
||||||
$key = trim($key);
|
$key = trim($key);
|
||||||
if (strpos($key, '$.') && false === strpos($key, '(')) {
|
if (strpos($key, '$.') && false === strpos($key, '(')) {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class Sqlite extends Builder
|
|||||||
* @param array $options
|
* @param array $options
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function parseKey($key, $options = [])
|
protected function parseKey($key, $options = [], $strict = false)
|
||||||
{
|
{
|
||||||
$key = trim($key);
|
$key = trim($key);
|
||||||
if (strpos($key, '.')) {
|
if (strpos($key, '.')) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
namespace think\db\builder;
|
namespace think\db\builder;
|
||||||
|
|
||||||
use think\db\Builder;
|
use think\db\Builder;
|
||||||
|
use think\db\Expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sqlsrv数据库驱动
|
* Sqlsrv数据库驱动
|
||||||
@@ -37,7 +38,9 @@ class Sqlsrv extends Builder
|
|||||||
if (is_array($order)) {
|
if (is_array($order)) {
|
||||||
$array = [];
|
$array = [];
|
||||||
foreach ($order as $key => $val) {
|
foreach ($order as $key => $val) {
|
||||||
if (is_numeric($key)) {
|
if ($val instanceof Expression) {
|
||||||
|
$array[] = $val->getValue();
|
||||||
|
} elseif (is_numeric($key)) {
|
||||||
if (false === strpos($val, '(')) {
|
if (false === strpos($val, '(')) {
|
||||||
$array[] = $this->parseKey($val, $options);
|
$array[] = $this->parseKey($val, $options);
|
||||||
} elseif ('[rand]' == $val) {
|
} elseif ('[rand]' == $val) {
|
||||||
@@ -72,8 +75,11 @@ class Sqlsrv extends Builder
|
|||||||
* @param array $options
|
* @param array $options
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function parseKey($key, $options = [])
|
protected function parseKey($key, $options = [], $strict = false)
|
||||||
{
|
{
|
||||||
|
if (is_int($key)) {
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
$key = trim($key);
|
$key = trim($key);
|
||||||
if (strpos($key, '.') && !preg_match('/[,\'\"\(\)\[\s]/', $key)) {
|
if (strpos($key, '.') && !preg_match('/[,\'\"\(\)\[\s]/', $key)) {
|
||||||
list($table, $key) = explode('.', $key, 2);
|
list($table, $key) = explode('.', $key, 2);
|
||||||
@@ -84,7 +90,7 @@ class Sqlsrv extends Builder
|
|||||||
$table = $options['alias'][$table];
|
$table = $options['alias'][$table];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!is_numeric($key) && !preg_match('/[,\'\"\*\(\)\[.\s]/', $key)) {
|
if ($strict || !preg_match('/[,\'\"\*\(\)\[.\s]/', $key)) {
|
||||||
$key = '[' . $key . ']';
|
$key = '[' . $key . ']';
|
||||||
}
|
}
|
||||||
if (isset($table)) {
|
if (isset($table)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user