Yii1曾经有过beforeFind方法,您可以在其中修改查询或其他任何您想要做的事情。
在Yii2中,建议的替代方法是使用modelQuery解决方案,例如
class MyModel extends \yii\db\ActiveRecord
{
public static function find()
{
return new MyModelQuery(get_called_class());
}
/* ... */
}
和
class MyModelQuery extends \yii\db\ActiveQuery
{
public function init( )
{
/** do something here **/
}
}
但是如何在MyModelQuery中传递或引用MyModel? 例如: -
class MyModelQuery extends \yii\db\ActiveQuery
{
public function init( )
{
$sql = "SET @variable = {$MyModel->variable1}";
}
}
修改
为了完整起见,我在未来添加了一个帮助他人的用例。
我已经在MySql下运行了嵌套视图,并且运行得非常糟糕。
在我的情况下,我有订单,订单商品和订单商品费用表,每个一对多到下一个,我想总结订单总数。我有嵌套视图,每个级别一个总和到上面的级别,但是在订单项和订单项费用级别MySql首先对整个表进行分组(我不能使用algorithm = merge,因为我有一个GROUP BY)
我正在实施Pushdown方法,您可以在其中定义要在子视图中使用的SQL变量,以缩小搜索范围,如下所示:http://code.openark.org/blog/mysql/views-better-performance-with-condition-pushdown 而且在这里 https://www.percona.com/blog/2010/05/19/a-workaround-for-the-performance-problems-of-temptable-views/
通过这种方式,如果我可以添加' WHERE order_id ='对于两个子视图的where子句,我将3.5秒查询减少到0.003秒查询。
因此,使用Salem的建议,我可以执行一条SQL语句' SET @ order_id = 1234'在我的查询之前,然后使用函数在订单项和订单项费用视图中选择。注意:这是特定于连接的,因此没有会话之间发生冲突的危险。
有点复杂但很快。
但是,看看SQL和PHP中的循环之间的性能比较可能会很有趣......
编辑2
实际上,你通常使用find()作为静态方法,所以没有办法使用$ this-> order_id,所以我把它更改为覆盖了findOne方法
public static function findOne( $orderId )
{
if ( isset($orderId) )
{
$sql = "SET @orderId='{$orderId}'";
Yii::$app->db->createCommand($sql)->execute();
}
return parent::findOne( $orderId );
}
我也将此视图用于其他搜索,因此在视图中我需要检查orderId是否已设置...
where (
CASE
WHEN ( NOT isnull( get_session_orderId() ) )
THEN `order`.order_id = get_session_cartref()
ELSE `order`.order_id LIKE '%'
END
)
答案 0 :(得分:1)
关于如何让ActiveQuery类参与检查我的答案:
Yii2 : ActiveQuery Example and what is the reason to generate ActiveQuery class separately in Gii?
但是如果您要做的事情不需要构建命名作用域,那么您可以通过以下方式覆盖find方法:
public static function find()
{
return parent::find()->where(['variable' => 'some value']);
}