在cakephp 2.5中是否可以做一个“BETWEEN?AND?”where条件LIKE?在cakephp 2.5中我写了这样的东西
'conditions' => ['start_date BETWEEN ? AND ?' => ['2014-01-01', '2014-12-32']]
我如何迁移它?另外,我会写这样的内容
'conditions' => [ '? BETWEEN start_date AND end_date'] => '2014-03-31']
ryhaxcpt1#
Between表达式都是支持开箱即用的,然而它们只支持第一种情况而没有额外的摆弄:
$Query = $Table ->find() ->where(function($exp) { return $exp->between('start_date', '2014-01-01', '2014-12-32', 'date'); });
如果你想通过between方法处理第二种情况,那么你必须将所有值作为表达式传递,这很容易出错,因为在这种情况下,它们不会受到转义/参数绑定的影响,你必须自己去做(这是绝对不推荐的!请参阅the manual for PDO::quote()中的安全说明),大致如下:
PDO::quote()
use Cake\Database\Expression\IdentifierExpression; use Cake\Database\Expression\QueryExpression; use Cake\ORM\Query; // ... $Query = $Table ->find() ->where(function(QueryExpression $exp, Query $query) { return $exp->between( $query->newExpr( $query->connection()->driver()->quote( '2014-03-31', \PDO::PARAM_STR ) ), new IdentifierExpression('start_date'), new IdentifierExpression('end_date') ); });
对于CakePHP附带的所有SQL方言都支持的这种基本SQL表达式来说,这可能有点不方便,因此您可能有理由在这里使用带有值绑定的原始SQL片段。然而,需要注意的是,表达式通常是更好的选择,例如跨方言支持,因为它们可以(或多或少)在编译时很容易地转换,参见SqlDialectTrait::_expressionTranslators()的实现。此外,表达式通常支持自动标识符引用。
SqlDialectTrait::_expressionTranslators()
通过手动值绑定,你几乎可以创建任何你喜欢的东西。但是应该注意的是,只要有可能,你应该使用表达式来代替,因为它们更容易移植,这已经在很多表达式中发生了。
$Query = $Table ->find() ->where([ 'start_date BETWEEN :start AND :end' ]) ->bind(':start', '2014-01-01', 'date') ->bind(':end', '2014-12-31', 'date');
这样第二种情况也可以很容易地解决,比如:
$Query = $Table ->find() ->where([ ':date BETWEEN start_date AND end_date' ]) ->bind(':date', '2014-03-31', 'date');
也可以将两者混合使用,即使用一个利用自定义绑定的表达式,大致如下:
use Cake\Database\Expression\IdentifierExpression; use Cake\Database\Expression\QueryExpression; use Cake\ORM\Query; // ... $Query = $Table ->find() ->where(function(QueryExpression $exp, Query $query) { return $exp->between( $query->newExpr(':date'), new IdentifierExpression('start_date'), new IdentifierExpression('end_date') ); }) ->bind(':date', '2014-03-31', 'date');
这样,您就可以使用可能的可移植表达式来处理第二种情况,而不必担心手动引用/转义输入数据和标识符。
话虽如此,最后BETWEEN与使用两个单独的简单条件是一样的,如下所示:一个但是不要生气,如果你一直读到这里,至少你学到了一些关于查询构建器的细节。
BETWEEN
*操作手册〉数据库访问和ORM〉查询生成器〉高级条件*API〉\蛋糕\数据库\查询::绑定()
目前似乎只有两个选项。核心现在支持这种开箱即用,以下仅供参考。
目前,ORM查询构建器(Cake\ORM\Query)(例如,在表对象上调用find()时检索的构建器)不支持值绑定
Cake\ORM\Query
find()
因此,为了能够使用绑定,您必须使用底层的数据库查询构建器(Cake\Database\Query),例如,可以通过**Connection::newQuery()**检索它。下面是一个例子:
Cake\Database\Query
Connection::newQuery()
$conn = ConnectionManager::get('default'); $Query = $conn->newQuery(); $Query ->select('*') ->from('table_name') ->where([ 'start_date BETWEEN :start AND :end' ]) ->bind(':start', new \DateTime('2014-01-01'), 'date') ->bind(':end', new \DateTime('2014-12-31'), 'date'); debug($Query->execute()->fetchAll());
这将导致类似于以下内容的查询
SELECT * FROM table_name WHERE start_date BETWEEN '2014-01-01' AND '2014-12-31'
另一个选择是定制expression类,它生成适当的SQL片段。列名应该被 Package 到标识符表达式对象中,以便它们被自动引用(如果启用了自动引用),key〉value数组语法用于绑定值,其中数组键是实际值,数组值是数据类型。
请注意,直接传递列名的用户输入是不安全的,因为它们没有被转义!请使用白名单或类似的列表来确保列名可以安全使用!
use App\Database\Expression\BetweenComparison; use Cake\Database\Expression\IdentifierExpression; // ... $between = new BetweenComparison( new IdentifierExpression('created'), ['2014-01-01' => 'date'], ['2014-12-31' => 'date'] ); $TableName = TableRegistry::get('TableName'); $Query = $TableName ->find() ->where($between); debug($Query->execute()->fetchAll());
这将生成一个类似于上面的查询。
use App\Database\Expression\BetweenComparison; use Cake\Database\Expression\IdentifierExpression; // ... $between = new BetweenComparison( ['2014-03-31' => 'date'], new IdentifierExpression('start_date'), new IdentifierExpression('end_date') ); $TableName = TableRegistry::get('TableName'); $Query = $TableName ->find() ->where($between); debug($Query->execute()->fetchAll());
另一方面,这将导致类似于以下内容的查询
SELECT * FROM table_name WHERE '2014-03-31' BETWEEN start_date AND end_date
namespace App\Database\Expression; use Cake\Database\ExpressionInterface; use Cake\Database\ValueBinder; class BetweenComparison implements ExpressionInterface { protected $_field; protected $_valueA; protected $_valueB; public function __construct($field, $valueA, $valueB) { $this->_field = $field; $this->_valueA = $valueA; $this->_valueB = $valueB; } public function sql(ValueBinder $generator) { $field = $this->_compilePart($this->_field, $generator); $valueA = $this->_compilePart($this->_valueA, $generator); $valueB = $this->_compilePart($this->_valueB, $generator); return sprintf('%s BETWEEN %s AND %s', $field, $valueA, $valueB); } public function traverse(callable $callable) { $this->_traversePart($this->_field, $callable); $this->_traversePart($this->_valueA, $callable); $this->_traversePart($this->_valueB, $callable); } protected function _bindValue($value, $generator, $type) { $placeholder = $generator->placeholder('c'); $generator->bind($placeholder, $value, $type); return $placeholder; } protected function _compilePart($value, $generator) { if ($value instanceof ExpressionInterface) { return $value->sql($generator); } else if(is_array($value)) { return $this->_bindValue(key($value), $generator, current($value)); } return $value; } protected function _traversePart($value, callable $callable) { if ($value instanceof ExpressionInterface) { $callable($value); $value->traverse($callable); } } }
nwsw7zdq2#
您可以使用以下两种方法之一。
方法1:
$start_date = '2014-01-01 00:00:00'; $end_date = '2014-12-31 23:59:59'; $query = $this->Table->find('all') ->where(function ($exp, $q) use($start_date,$end_date) { return $exp->between('start_date', $start_date, $end_date); }); $result = $query->toArray();
方法二:
$start_date = '2014-01-01 00:00:00'; $end_date = '2014-12-31 23:59:59'; $query = $this->Table->find('all') ->where([ 'start_date BETWEEN :start AND :end' ]) ->bind(':start', new \DateTime($start_date), 'datetime') ->bind(':end', new \DateTime($end_date), 'datetime'); $result = $query->toArray();
0tdrvxhp3#
"我就这样用它"
$this->Table->find()->where(['data_inicio BETWEEN '.'\''.$data_inicio.'\''.' AND .'\''.$data_final.'\''.' ']);
zyfwsgd64#
大家好请使用此查询获取数据的基础范围值
$query = $this->Leads->find('all', array('conditions'=>array('postcode BETWEEN '.$postcodeFrom.' and'.$postcodeTo.''), 'recursive'=>-1)); debug($query); print_r($query->toArray());
4条答案
按热度按时间ryhaxcpt1#
表达式
Between表达式都是支持开箱即用的,然而它们只支持第一种情况而没有额外的摆弄:
如果你想通过between方法处理第二种情况,那么你必须将所有值作为表达式传递,这很容易出错,因为在这种情况下,它们不会受到转义/参数绑定的影响,你必须自己去做(这是绝对不推荐的!请参阅the manual for
PDO::quote()
中的安全说明),大致如下:对于CakePHP附带的所有SQL方言都支持的这种基本SQL表达式来说,这可能有点不方便,因此您可能有理由在这里使用带有值绑定的原始SQL片段。
然而,需要注意的是,表达式通常是更好的选择,例如跨方言支持,因为它们可以(或多或少)在编译时很容易地转换,参见
SqlDialectTrait::_expressionTranslators()
的实现。此外,表达式通常支持自动标识符引用。值绑定
通过手动值绑定,你几乎可以创建任何你喜欢的东西。但是应该注意的是,只要有可能,你应该使用表达式来代替,因为它们更容易移植,这已经在很多表达式中发生了。
这样第二种情况也可以很容易地解决,比如:
两者的混合(最安全、最兼容的方法)
也可以将两者混合使用,即使用一个利用自定义绑定的表达式,大致如下:
这样,您就可以使用可能的可移植表达式来处理第二种情况,而不必担心手动引用/转义输入数据和标识符。
使用数组语法进行常规比较
话虽如此,最后
BETWEEN
与使用两个单独的简单条件是一样的,如下所示:一个
但是不要生气,如果你一直读到这里,至少你学到了一些关于查询构建器的细节。
另请参阅
*操作手册〉数据库访问和ORM〉查询生成器〉高级条件
*API〉\蛋糕\数据库\查询::绑定()
目前似乎只有两个选项。核心现在支持这种开箱即用,以下仅供参考。
值绑定(通过数据库查询生成器)
目前,ORM查询构建器(
Cake\ORM\Query
)(例如,在表对象上调用find()
时检索的构建器)不支持值绑定因此,为了能够使用绑定,您必须使用底层的数据库查询构建器(
Cake\Database\Query
),例如,可以通过**Connection::newQuery()
**检索它。下面是一个例子:
这将导致类似于以下内容的查询
自定义表达式类
另一个选择是定制expression类,它生成适当的SQL片段。
列名应该被 Package 到标识符表达式对象中,以便它们被自动引用(如果启用了自动引用),key〉value数组语法用于绑定值,其中数组键是实际值,数组值是数据类型。
请注意,直接传递列名的用户输入是不安全的,因为它们没有被转义!请使用白名单或类似的列表来确保列名可以安全使用!
值之间的字段
这将生成一个类似于上面的查询。
字段之间的值
另一方面,这将导致类似于以下内容的查询
表达式类
nwsw7zdq2#
您可以使用以下两种方法之一。
方法1:
方法二:
0tdrvxhp3#
"我就这样用它"
zyfwsgd64#
大家好请使用此查询获取数据的基础范围值