Yii2:如何覆盖yii \ db \ Query类以添加查询的默认条件

时间:2018-03-07 12:51:26

标签: yii2 yii2-advanced-app yii-components

我想创建一个基于云的应用程序,我将应用程序ID和branch_id存储在会话中,并且我想将application_idbranch_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();

1 个答案:

答案 0 :(得分:2)

一种方法是扩展Query类并覆盖特征where() from()select(),并将命名空间从yii\db\Query更改为{{ 1}}在您希望添加条件的模型中总体而言。但请记住,您有责任确保所有这些表格在表格中包含这两个字段(common\components\Queryapplication_id),您可以将branch_id替换为yii\db\Query。< / p>

为什么要覆盖common\components\Query where()from()?您可以使用以下格式编写查询。

我们假设我们有select()表格,其中包含字段productid,现在请考虑以下查询。

name

以上将生成以下SQL查询

$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();

因此,您需要在默认情况下将两个条件添加到上面的所有条件

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`='') 中创建文件名Query并添加以下内容,

  

注意:我已为列添加了硬编码值的条件   像这样common/components替换   它们与实际使用前的会话中的相应变量一起使用   它用于测试目的,你可以保持原样。我假设你想要上述两个   要在查询中添加[ 'application_id' => 1 ] , [ 'branch_id' => 1 ]条件的字段。

and

现在测试它会在<?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

希望能帮助您或其他人寻找相同的解决方案

修改

我更新了上面的类,并使用连接添加了对查询的修复,这会引发错误

  

专栏&#39; company_id&#39; in where子句不明确

我添加了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) 数组中可用的第一个table名称,因为所有表都有字段名称,并且添加第一个选定表的条件将起作用,因为它将与下一个表连​​接具有from条件的表格。 我已经从班级中删除了ON特质覆盖,因为我们不需要它。