Yii1转Yii2:CDbCriteria替代方案及代码迁移咨询
Yii 1 to Yii 2 Migration: CDbCriteria Replacement & Query Best Practices
Hey there! Let's walk through migrating your Yii 1 code to Yii 2, and answer your question about ActiveQuery vs Query.
1. Full Code Rewrite for Yii 2
First, let's fix up your code to fit Yii 2's conventions. Note that Yii 2 removes CDbCriteria and replaces it with ActiveQuery (for ActiveRecord-based queries) or the general Query class. Also, the model() method is no longer needed in Yii 2—we use static find() instead.
Assumptions
I'll assume your model class is named Logs (mapped to the logs table) and it extends yii\db\ActiveRecord.
Rewritten Code
<?php namespace app\models; use yii\db\ActiveRecord; use yii\data\ActiveDataProvider; use Yii; class Logs extends ActiveRecord { /** * @inheritdoc */ public static function tableName() { return 'logs'; } /** * Search method replacement for Yii 2 * Replaces CDbCriteria with ActiveQuery */ public function search() { // Initialize ActiveQuery tied to our Logs model $query = Logs::find(); // Use andFilterWhere to mimic CDbCriteria->compare() behavior // It automatically skips empty values, just like compare() $query->andFilterWhere(['id' => $this->id]) ->andFilterWhere(['like', 'hashkey', $this->hashkey]) ->andFilterWhere(['like', 'ch', $this->ch]) ->andFilterWhere(['like', 'cimi', $this->cimi]) ->andFilterWhere(['like', 'dir', $this->dir]) ->andFilterWhere(['like', 'ourl', $this->ourl]) ->andFilterWhere(['like', 'imob', $this->imob]) ->andFilterWhere(['like', 'tStart', $this->tStart]) ->andFilterWhere(['like', 'tAnswer', $this->tAnswer]) ->andFilterWhere(['like', 'tEnd', $this->tEnd]) ->andFilterWhere(['like', 'state', $this->state]) ->andFilterWhere(['like', 'omob', $this->omob]) ->andFilterWhere(['like', 'date', $this->date]); // Return ActiveDataProvider with our query return new ActiveDataProvider([ 'query' => $query, ]); } /** * Get incoming calls (fixed Yii 2 DB access + added date filter support) */ public function getInCalls($fromDate = false, $toDate = false) { $sql = "SELECT id, date as Date, ch as Channel, dir as Direction, ourl as Twinkle, imob as IncomingCall, state as State FROM logs WHERE tAnswer LIKE '%+%'"; // Add date filter if parameters are provided if ($fromDate && $toDate) { $sql .= " AND date BETWEEN :fromDate AND :toDate"; } $sql .= " GROUP BY date ORDER BY date DESC"; $command = Yii::$app->db->createCommand($sql); // Bind parameters to prevent SQL injection if ($fromDate && $toDate) { $command->bindValues([ ':fromDate' => $fromDate, ':toDate' => $toDate, ]); } return $command->queryAll(); } /** * Get outgoing calls (fixed Yii 2 DB access + added date filter support) */ public function getOutCalls($fromDate = false, $toDate = false) { $sql = "SELECT id, date as Date, ch as Channel, dir as Direction, ourl as Twinkle, state as State, omob as OutgoingCall FROM logs WHERE state LIKE 'Mobile%' AND (omob LIKE '07%' OR omob LIKE '+%')"; if ($fromDate && $toDate) { $sql .= " AND date BETWEEN :fromDate AND :toDate"; } $sql .= " GROUP BY date ORDER BY date DESC"; $command = Yii::$app->db->createCommand($sql); if ($fromDate && $toDate) { $command->bindValues([ ':fromDate' => $fromDate, ':toDate' => $toDate, ]); } return $command->queryAll(); } /** * Get missed calls (fixed Yii 2 DB access + added date filter support) */ public function getMissedCalls($fromDate = false, $toDate = false) { $sql = "SELECT id, date as Date, ch as Channel, state as State, imob as Missed, ourl as Agent FROM logs WHERE tEnd LIKE '%+%' AND imob IS NOT NULL AND state LIKE '%Lan%' AND tAnswer NOT LIKE '%+%' AND (imob LIKE '07%' OR imob LIKE '+%')"; if ($fromDate && $toDate) { $sql .= " AND date BETWEEN :fromDate AND :toDate"; } $sql .= " GROUP BY date ORDER BY date DESC"; $command = Yii::$app->db->createCommand($sql); if ($fromDate && $toDate) { $command->bindValues([ ':fromDate' => $fromDate, ':toDate' => $toDate, ]); } return $command->queryAll(); } }
Key Changes Explained
search()Method: ReplacedCDbCriteriawithActiveQuery(viaLogs::find()).andFilterWhere()acts exactly likeCDbCriteria->compare()—it skips empty filter values automatically.- DB Access: Changed
Yii::app()->dbtoYii::$app->db(Yii 2's way of accessing application components). - Date Filters: Added support for your unused
$fromDate/$toDateparameters with parameter binding to avoid SQL injection. - Removed
model(): Yii 2 uses staticLogs::find()instead ofLogs::model().
2. ActiveQuery vs Query: Which is Better?
Let's break down the use cases for each:
ActiveQuery (Best for Your search() Method)
- Tied to ActiveRecord: Returns
Logsmodel instances instead of raw arrays. This means you can use model methods, validation, and associations directly on the results. - Built-in Convenience: Works seamlessly with
ActiveDataProvider(used in GridViews/ListViews), and supports Yii 2's query builders for safe, readable conditions. - Ecosystem Integration: Leverages ActiveRecord features like attribute labels, events, and behaviors.
Query (Better for Raw Data Queries)
- General-Purpose: A lower-level class that returns raw arrays/scalars. Great for complex queries that don't need to map to a model, or when you want maximum control over the result format.
- Flexibility: Can be used for cross-table queries, aggregations, or cases where you don't need ActiveRecord overhead.
Recommendation for Your Code
- Use ActiveQuery for the
search()method—it's the standard approach in Yii 2 for filtering and displaying model data in UI components. - For your
getInCalls()/getOutCalls()/getMissedCalls()methods:- If you just need raw array data (like you did in Yii 1), sticking with
createCommand()(as I did above) or usingQueryis fine. - If you want to work with
Logsmodel instances instead of arrays, you could rewrite these methods to useActiveQuery(e.g.,Logs::find()->select(...)->where(...)).
- If you just need raw array data (like you did in Yii 1), sticking with
内容的提问来源于stack exchange,提问作者xbile
相关产品推荐
相关产品推荐

