ynamics / relatedsearchbehavior
简化在 CGridView 中搜索关系以及使用关系的操作
README
Yii 扩展 - RelatedSearchBehavior
使用此行为简化创建与相关表相关联的 CGridView 或从相关表获取字段。它神奇地添加了所需的 'with' 子句,并提供了关系记录字段的自定义别名。
使用 KeenActiveDataProvider 扩展来限制对数据库的请求数量。
需求 ¶
适用于 Yii 1.1.12-1.1.26 版本。
论坛 ¶
关于此扩展的论坛主题 可在此找到。
用法 ¶
要使用此扩展,您必须执行以下 5 个步骤
- "安装" RelatedSearchBehavior;
- 更新模型的 search() 方法;
- 添加/更新 'behaviors()' 方法;
- 将搜索字段添加到模型规则中作为安全字段;
- 将搜索字段用作 CGridView 中的任何其他字段。
以下是这些步骤的详细信息
1. "安装" RelatedSearchBehavior; ¶
安装就像将位置添加到 Yii 配置文件 (main.php) 的 'import' 配置中一样简单
return array( [...] 'import'=>array( [...] 'ext.KeenActiveDataProvider', 'ext.RelatedSearchBehavior', ),
在上面的例子中,RelatedSearchBehavior 文件被放置在 extensions 目录中。
2. 更新模型的 search() 方法; ¶
更新 ActiveRecord::search() 的重载。以下示例显示了如何设置默认的搜索顺序。您可以在第二个数组中设置任何由 CActiveDataProvider 接受的参数(如分页)。因此,将以下代码替换为
return new CActiveDataProvider($this, array( 'criteria'=>$criteria, 'sort'=>array( 'defaultOrder'=>'title ASC', ) ));
为以下代码(我更喜欢使用如 '$sort' 这样的中间变量来提高可读性和灵活性)
$sort=array( 'defaultOrder'=>'title ASC', ); return $this->relatedSearch( $criteria, array('sort'=>$sort) );
在上面的示例中,'title' 可以是您定义的相关字段之一。
3. 添加/更新 'behaviors()' 方法 ¶
将行为附加到 CActiveRecord 并指定相关字段。
function behaviors() { return array( 'relatedsearch'=>array( 'class'=>'RelatedSearchBehavior', 'relations'=>array( 'serial'=>'device.device_identifier', 'location'=>'device.location.description', 'fieldwithdifferentsearchvalue'=>array( 'field'=>'device.displayname', 'searchvalue'=>'deviceid' ), 'mylocalreference'=>'field.very.far.away.in.the.relation.tree', ), ), ); }
4. 将搜索字段添加到模型规则中作为安全字段; ¶
public function rules() { return array( [...] array('serial,location,deviceid','safe','on'=>'search'), ); }
5. 将搜索字段用作 CGridView 中的任何其他字段。 ¶
对于 CGridView 列指定,您可以为列简单地使用 'serial'(不需要做 'name'=>..., 'filter'=>..., 'value'=>...)。
示例
$this->widget('zii.widgets.grid.CGridView', array( [...] 'columns'=>array( [...] 'serial', 'location', ) ));
6. 要使用 "autoScope" ¶
Autoscope 允许您使用范围搜索字段,而无需自己声明该范围。
例如,您可以使用此
MyModel::model()->location('Belgium')->findAll();
之前,您必须
- 将 RelatedSearchBehavior 添加到您的 CActiveRecord 的行为中(已在前面步骤中完成,
- 将以下通用代码添加到您的 CActiveRecord 模型中。
public function __call($name,$parameters) { try { return parent::__call($name,$parameters); } catch (CException $e) { if(preg_match( '/'.Yii::t( 'yii', quotemeta( Yii::t( 'yii', '{class} and its behaviors do not have a method or closure named "{name}".' ) ), array('{class}'=>'.*','{name}'=>'.*') ) .'/',$e->getMessage())) { return $this->autoScope($name, $parameters); } else { throw $e; } } }
您允许提供所有常规比较参数
MyModel::model()->location($searchvalue,$partialMatch,$operator,$escape)->findAll();
默认值与 compare: autoscope(,false,"AND",false) 相同。
这在复杂嵌套条件下很有用,对于像上述简单的搜索这样的简单搜索则不太有用。
7. 在CSort属性中使用关系进行排序。¶
'CSort' 允许您指定如Yii文档中所述的'虚拟属性'进行排序。[链接](https://yiiframework.cn/doc/api/1.1/CSort#attributes-detail)。在没有RelatedSearchBehavior的情况下,您必须确保包含在搜索条件中使用的关联。有了RelatedSearchBehavior,您就不必担心这个问题 - 扩展会为您处理(自1.16版起)。
$sort=array( 'defaultOrder'=>'title ASC', 'attributes'=> array( 'price'=>array( 'asc'=>'item.price', 'desc'=>'item.price DESC', 'label'=>'Item Price' ), ), ); return $this->relatedSearch( $criteria, array('sort'=>$sort) );
首选的方法是使用为RelatedSearchBehavior定义的属性,但在组合排序条件下这可能会很有用。
$sort=array( 'defaultOrder'=>'title ASC', 'attributes'=> array( 'groupprice'=>array( 'asc'=>'item.group, item.price', 'desc'=>'item.group DESC, item.price DESC', 'label'=>'Item Price' ), ), ); return $this->relatedSearch( $criteria, array('sort'=>$sort) );
8. exactSearchAttributes ¶
当在CActiveRecord
中定义了CActiveRecord::exactSearchAttributes
时,那里列出的属性默认情况下是精确匹配,而不是部分匹配。这在与表组合使用时特别有用,并且适用于列(不仅仅是关联)。例如,ID不应该部分匹配,id "1" 也会匹配10..19,21,31等。要求精确匹配还可以提高搜索性能,因为当使用索引时这更合适。
示例
public function exactSearchAttributes() { return [ 'is_active', 'context_id', 'entity_id', 'type_id', ]; }
在上面的例子中
is_active
是布尔值,所以精确匹配在这里是完美的;context_id
是一个与UI中的描述相匹配的概念;entity_id
匹配某些实体,也显示为特定于实体的标签;type_id
定义了记录的类型,并且也匹配某些标签。
9. 小贴士与注意事项 ¶
- 如果您喜欢RelatedSearchBehavior,您可以通过创建或更新Gii模板来自动生成它。
- 如果您使用'ERememberFiltersBehavior',在获取dataProvider之前必须设置rememberScenario - 否则,在排序子句中关系将不会解析。所以您编写
$model->rememberScenario="admin"; $dataProvider=$model->search();
这是作者使用此扩展的项目中的搜索方法。所有模型都从YActiveRecord扩展,而YActiveRecord又从CActiveRecord扩展并实现了对默认CActiveRecord功能的几个扩展。它实现了以下搜索方法(RelatedSearchBehavior必须添加到模型类本身)
/** * Search method valid for all Active Records (with RelatedSearchBehavior) * * @return KeenActiveDataProvider */ public function search() { $criteria=new CDbCriteria(); $t=$this->getTableAlias(false, false); $ds=$this->getDbConnection()->getSchema(); $columns=$this->getMetaData()->columns; //$relations=$this->relations; foreach ($this->getSafeAttributeNames() as $attribute) { $value=$this->{$attribute}; if ($value==='=') { $value=array(null,''); } if (is_array($value)&&!empty($value)||(!is_array($value)&&"$value" !== "")) { if (isset($columns[$attribute])) { if (in_array($attribute,$this->exactSearchAttributes())) { Yii::trace("Exact match required for $attribute"); } $criteria->compare($ds->quoteColumnName("$t.$attribute"), $value, !$columns[$attribute]->isForeignKey &&!in_array($attribute,$this->exactSearchAttributes()) ); } /** * Sample code to handle exceptions (fields that are not in * relations). * ```php * else if (!isset($relations[$attribute])) { * // Not a related search item -> do something else * $this->compareProperty($attribute, $value,true); * } * ``` */ } } // $criteria->together=true; return $this->relatedSearch($criteria //,array('sort'=>array('defaultOrder'=>$this->getTableAlias(true,false).'.entity_id DESC')) ); } /** * Provides the list of attributes for which an exact search is * needed and not a partial search. * (typical: keys, enums, etc. * @return string[] */ public function exactSearchAttributes() { return []; }
历史 ¶
查看RelatedSearchbehavior.php
以了解版本的简要描述