2016-05-23 46 views
2

Yii1曾經有beforeFind方法,其中你可以修改查詢或任何其他你可能想這樣做。Yii2 - 替代beforeFind優化嵌套視圖在MySQL

在Yii2建議的替代方法是使用例如內MyModelQuery的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 **/ 
    } 
} 

但如何通過或參考爲MyModel? 例如: -

class MyModelQuery extends \yii\db\ActiveQuery 
{ 
    public function init() 
    { 
    $sql = "SET @variable = {$MyModel->variable1}"; 
    } 
} 

編輯

爲了完整起見,我添加了一個使用案例,以幫助別人的未來。

我已經被MySQL下運行的嵌套組的意見,它運行得很厲害。

在我的情況,我有訂單,訂單項和訂單項目,收費表,每一個一對多到下一個,我想總結的訂單總數。我有嵌套視圖,在每個級別一個總和到上面的級別,但在訂單項目和訂單項目費用水平MySql是整組首先(我不能使用算法=合併,因爲我有一個GROUP BY) 。

我執行,可以定義爲在這裏列出一個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子句中添加'WHERE order_id =',我將3.5秒查詢減少到0.003秒查詢。

因此,在下面的Salem的建議中,我可以在查詢之前執行一條SQL語句'SET @ order_id = 1234',然後使用函數在訂單項和訂單項費用視圖中選取。注意:這是特定於連接的,所以沒有會話之間發生衝突的危險。

有點複雜但很快。

這將是有趣的,不過,看到SQL和PHP或許循環之間的性能比較....

EDIT 2

事實上,你通常使用find()作爲一個靜態方法,所以沒有使用的方式$這個 - > 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

你能提供一個特定的樣本嗎? ..請 – scaisEdge

回答

1

關於如何參與的ActiveQuery類檢查我的答案在這裏:

Yii2 : ActiveQuery Example and what is the reason to generate ActiveQuery class separately in Gii?

但是,如果你正在嘗試做的,不需要建立命名範圍,那麼你可以簡單地覆蓋查找方法如下:

public static function find() 
{ 
    return parent::find()->where(['variable' => 'some value']); 
} 
+1

是的,當然,這是完美的!謝謝。 – ChrisB

+1

雖然,你不能在靜態上下文中使用$ this。見上面的EDIT2。 – ChrisB

+0

哦,是的,你是對的。我從一個代碼中做了一個快速複製/過去,我從Yii :: $ app-> user'類中獲取了值。我剛剛編輯了我的答案,不要混淆別人。感謝您指出。另一個選項可能是在我鏈接的例子中使用了一個名爲scope的參數,例如'big($ threshold = 100)',但是你每次都需要執行'Model :: find() - > big($ value)'。我建議添加您的解決方案作爲對此的答案。 –