我想创建一个基于云的应用程序,在 session 中存储应用程序 ID 和 branch_id
,并且我想添加 application_id
和 branch_id
到每个数据库查询。
很简单,我使用覆盖find()
public static function find()
{
return parent::find()->where([]);
}
但问题是我如何重写这样的查询
$total_return_price = (new Query())
->select('SUM(product_order.order_price * product_order.quantity) as return_price')
->from('order')
->innerJoin('product_order', 'product_order.order_id = order.id')
->where(['=', 'order.user_id', $user_id])
->andWhere(['=', 'order.status', '4'])
->one();
最佳答案
一种方法是扩展 Query
类并覆盖特征 where()
from()
和select()
并从 yii\db\Query
更改命名空间至common\components\Query
总体而言,在您想要添加条件的模型中。但请记住,您有责任确保所有这些表在替换 application_id
的表内都具有这两个字段( branch_id
和 yii\db\Query
)。与 common\components\Query
.
为什么要覆盖 where()
from()
和select()
?您可以使用以下格式编写查询。
假设我们有一个 product
包含字段 id
的表和name
,现在考虑以下查询。
$q->from ( '{{product}}' )
->all ();
$q->select ( '*' )
->from ( '{{product}}' )
->all ();
$q->from ( '{{product}}' )
->where ( [ 'name' => '' ] )
->all ();
$q->from ( '{{product}}' )
->andWhere ( [ 'name' => '' ] )
->all ();
$q->select ( '*' )
->from ( '{{product}}' )
->where ( [ 'IN' , 'id' , [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 89 , 0 ] ] )
->andwhere ( [ 'name' => '' ] )
->all ();
$q->select ( '*' )
->from ( '{{product}}' )
->where ( [ 'and' ,
[ 'IN' , 'id' , [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 89 , 0 ] ] ,
[ 'name' => '' ]
] )
->all();
上面将生成以下 SQL 查询
SELECT * FROM `product`
SELECT * FROM `product`
SELECT * FROM `product` WHERE (`name`='')
SELECT * FROM `product` WHERE (`name`='')
SELECT * FROM `product` WHERE (`id` IN (1, 2, 3, 4, 5, 6, 7, 89, 0)) AND (`name`='')
SELECT * FROM `product` WHERE (`id` IN (1, 2, 3, 4, 5, 6, 7, 89, 0)) AND (`name`='')
所以你需要添加上面所有默认带有两个where条件的查询
创建文件名Query
在 common/components
内 并添加以下内容,
Note: I have added conditions with hardcoded values for the columns like this
[ 'application_id' => 1 ] , [ 'branch_id' => 1 ]
replace them with the respective variables from the session before actually using it for testing purpose you can keep as is.I assume that you want the above two fields to be added with anand
condition in the query.
<?php
namespace common\components;
use yii\db\Query as BaseQuery;
class Query extends BaseQuery {
/**
*
* @param type $condition
* @param type $params
* @return $this
*/
public function where( $condition , $params = array() ) {
parent::where ( $condition , $params );
$defaultConditionEmpty = !isset ( $this->where[$this->from[0] . '.company_id'] );
if ( $defaultConditionEmpty ) {
if ( is_array ( $this->where ) && isset ( $this->where[0] ) && strcasecmp ( $this->where[0] , 'and' ) === 0 ) {
$this->where = array_merge ( $this->where , [ [ $this->from[0] . '.company_id' => 1 ] , [ $this->from[0] . '.branch_id' => 1 ] ] );
} else {
$this->where = [ 'and' , $this->where , [ $this->from[0] . '.company_id' => 1 ] , [ $this->from[0] . '.branch_id' => 1 ] ];
}
}
return $this;
}
/**
*
* @param type $tables
* @return $this
*/
public function from( $tables ) {
parent::from ( $tables );
$this->addDefaultWhereCondition ();
return $this;
}
/**
* Private method to add the default where clause
*/
private function addDefaultWhereCondition() {
if ( $this->from !== null ) {
$this->where = [ 'and' ,
[ $this->from[0] . '.company_id' => 1 ] , [ $this->from[0] . '.branch_id' => 1 ]
];
}
}
}
现在要测试它,请在 SiteController
中创建一个测试操作像下面一样并访问它
public function actionTest() {
$q = new \common\components\Query();
echo $q->from ( '{{product}}' )->createCommand ()->rawSql;
echo "<br>";
echo $q->select ( '*' )->from ( '{{product}}' )->createCommand ()->rawSql;
echo "<br/>";
echo $q->from ( '{{product}}' )->where ( [ 'name' => '' ] )->createCommand ()->rawSql;
echo "<br>";
echo $q->from ( '{{product}}' )->andWhere ( [ 'name' => '' ] )->createCommand ()->rawSql;
echo "<br>";
echo $q->select ( '*' )->from ( '{{product}}' )->where ( [ 'IN' , 'id' , [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 89 , 0 ] ] )->andwhere ( [ 'name' => '' ] )->createCommand ()->rawSql;
echo "<br />";
echo $q->select ( '*' )->from ( '{{product}}' )
->where ( [ 'and' ,
[ 'IN' , 'id' , [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 89 , 0 ] ] ,
[ 'name' => '' ]
] )
->createCommand ()->rawSql;
return;
}
不用担心 product
表我们需要检查生成的查询,因此我们不执行查询而是使用 ->createCommand()->rawSql
打印构建的查询。因此,访问上述操作,它现在应该打印您的查询,并添加了如下所示的两列
SELECT * FROM `product` WHERE (`application_id`=1) AND (`branch_id`=1)
SELECT * FROM `product` WHERE (`application_id`=1) AND (`branch_id`=1)
SELECT * FROM `product` WHERE (`name`='') AND (`application_id`=1) AND (`branch_id`=1)
SELECT * FROM `product` WHERE (`application_id`=1) AND (`branch_id`=1) AND (`name`='')
SELECT * FROM `product` WHERE (`id` IN (1, 2, 3, 4, 5, 6, 7, 89, 0)) AND (`application_id`=1) AND (`branch_id`=1) AND (`name`='')
SELECT * FROM `product` WHERE (`id` IN (1, 2, 3, 4, 5, 6, 7, 89, 0)) AND (`name`='') AND (`application_id`=1) AND (`branch_id`=1)
希望对您或正在寻找相同解决方案的其他人有所帮助
编辑
我更新了上面的类,并使用联接添加了对查询的修复,这会引发错误
Column 'company_id' in where clause is ambiguous
我添加了第一个 table
名称可在 from
中找到数组,因为所有表都有字段名称,并且添加第一个选定表的条件将起作用,因为它将与下一个表使用 ON
连接健康)状况。
我已经删除了 select()
从类中覆盖特征,因为我们不需要它。
关于Yii2:如何覆盖 yii\db\Query 类以添加查询的默认条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49152429/