框架深入 - yii\db\Expression ¶
本文导航
作者:KK
发表日期:2017.3.25
快速了解 ¶
yii\db\Expression是一个代表了“数据库表达式”的类
通过以下代码可以快速了解它:
$query1 = new \yii\db\Query();
$command1 = $query1->from('user')->where(['<=', 'add_time', 'NOW()'])->createCommand();
echo $command1->rawSql; // SELECT * FROM `user` WHERE `add_time` <= 'NOW()' 重点是这个NOW()被单引号包住了
//------用Expression类传入表达式------
$query2 = new \yii\db\Query();
$expression = new \yii\db\Expression('NOW()');
$command2 = $query2->from('user')->where(['<=', 'add_time', $expression])->createCommand();
echo $command2->rawSql; // SELECT * FROM `user` WHERE `add_time` <= NOW() 没有引号包住NOW()
好了这下应该清楚了
解读 ¶
如果不用Expression ¶
条件里面有函数等表达式的话,会被当成字符串用'
号引住,因为框架要实现防注入
当查询构造器遇到Expression ¶
它会将表达式原封不动地加入查询语句里,不会加任何引号
其实这个Expression类里面的代码很简单:
namespace yii\db;
class Expression extends \yii\base\Object
{
public $expression;
public $params = [];
public function __construct($expression, $params = [], $config = [])
{
$this->expression = $expression;
$this->params = $params;
parent::__construct($config);
}
public function __toString()
{
return $this->expression;
}
}
如果光看Expression类的代码一般是不能快速理解是怎么发生作用的,那么这样的代码如何产生作用?
再看看我这段虚拟的框架底层处理逻辑:
function buildWhere($condition){
$where = '';
$value = $condition['add_time'];
if(gettype($value) != 'object'){
$where .= "add_time <= '" . $value . "'"; // 加了引号
}elseif($value instanceof \yii\db\Expression){
$where .= 'add_time <= ' . $value; //触发了Expression的toString,于是表达式原样拼接
}
return $where;
}
你在@vendor/yiisoft/yii2/db目录的所有php文件里全词大小写匹配搜索一下Expression
就可以更全面地了解它的处理逻辑了
也可以用在value里 ¶
比如下面这样将表达式放在更新方法的value里实现所有vip用户金币+9999
$data = ['gold' => new \yii\db\Expression('gold + 9999')];
$command = Yii::$app->db->createCommand()->update('user', $data, ['vip' => 1]);
echo $command->rawSql; // UPDATE `user` SET `gold`= gold + 9999 WHERE `vip`=1
更多例子 ¶
通过Expression传入自由的SQL合法表达式
$query1 = new \yii\db\Query();
$command1 = $query1
->from('user')
->where(['<=', 'age', new \yii\db\Expression('33 + 99')])
->createCommand();
echo $command1->rawSql; // SELECT * FROM `user` WHERE `age` <= 33 + 99
$query2 = new \yii\db\Query();
$expression = new \yii\db\Expression('DATE_SUB(NOW(), INTERVAL 1 MONTH)');
$command2 = $query2
->from('article')
->where(['date' => $expression])
->createCommand();
echo $command2->rawSql; // SELECT * FROM `article` WHERE `date` = DATE_SUB(NOW(), INTERVAL 1 MONTH)