首先我們有兩個模型它們直接有關聯
class Author extends CActiveRecord { ... } class Post extends CActiveRecord { ... function relations() { return array( 'author'=>array( self::BELONGS_TO, 'Author', 'id_author' ), ); } ... }
當以網格形式顯示所有 Post 時,我們希望顯示作者的名字,並且可以通過作者名字中的關鍵字過濾 Post。提供這些功能的最好解決方式(在我看來)是:
首先需要在 Post 模型中添加一個新的屬性,它用來保存搜索的字符串(即要搜索的作者名).也可以使用外鍵列來實現同樣的效果,但是我不喜歡這麼用,在搜索條件中保存搜索的字符串而不是外鍵 id.你還須在搜索條件中將這個新的屬性的規則設置為 safe。
class Post extends CActiveRecord { public $author_search; ... public function rules() { return array( ... array( 'xxx,yyy,author_search', 'safe', 'on'=>'search' ), ); } }
現在就可以在搜索條件(標准情況-每個模型都要一個 search 方法)中使用這個屬性了。同時,我們需要使用條件的 ‘with’ 屬性來指定我們的 Post 是通過哪個關系來獲取作者(這種方式只需一次數據庫查詢而不是延遲加載中的多次查詢
<?php $criteria = new CDbCriteria;$criteria->with = array( 'author' ); ... $criteria->compare( 'author.username', $this->author_search, true ); ... ?>
當我們修改搜索函數時,我們對返回的 CActiveDataProvider 添加一個新的功能
<?php return new CActiveDataProvider( 'Post', array( 'criteria'=>$criteria, 'sort'=>array( 'attributes'=>array( 'author_search'=>array( 'asc'=>'author.username', 'desc'=>'author.username DESC', ), '*', ), ), ); ); ?>
配置中排序部分的 attributes允許我們覆蓋默認值。當我們按 author_search字段排序的時候,它將會按照指定的規則排序,最後的 *表示其他字段按默認排序。通過這種方式我們也可以修改默認屬性的排序(例如:用戶指定按 last_name 列排序時,應該使用last_name和first_name結合排序).
到現在為止我們已經為我們的網格顯示做好了前期准備
<?php $this->widget('zii.widgets.grid.CGridView', array( 'dataProvider'=>$model->search(), 'filter'=>$model, 'columns'=>array( 'title', 'post_time', array( 'name'=>'author_search', 'value'=>'$data->author->username' ), array( 'class'=>'CButtonColumn', ), ), ); ); ?>
這就是所有,我們使用用戶名代替用戶ID外鍵列來排序,並且我們可以使用姓名關鍵字搜索.