简体   繁体   English

Yii - 使用高级搜索查询自定义CGridView的操作

[英]Yii - Query Manipulation for Custom CGridView with Advanced Search

So, I've extended CGridView to include an Advanced Search feature tailored to the needs of my organization. 因此,我扩展了CGridView,以包含根据我的组织需求量身定制的高级搜索功能。

  • Filter - lets you show/hide columns in the table, and you can also reorder columns by dragging the little drag icon to the left of each item. 过滤器 - 允许您显示/隐藏表格中的列,还可以通过拖动每个项目左侧的小拖动图标来重新排序列。
  • Sort - Allows for the selection of multiple columns, specify Ascending or Descending. 排序 - 允许选择多个列,指定升序或降序。
  • Search - Select your column and insert search parameters. 搜索 - 选择列并插入搜索参数。 Operators tailored to data type of selected column. 根据所选列的数据类型定制的运算符。

高级搜索截图

Version 1 works, albeit slowly. 版本1工作,虽然很慢。 Basically, I had my hands in the inner workings of CGridView , where I snatch the results from the DataProvider and do the searching and sorting in PHP before rendering the table contents. 基本上,我参与了CGridView的内部工作,在那里我从DataProvider抓取结果并在渲染表内容之前在PHP中进行搜索和排序。

Now writing Version 2, where I aim to focus on clever CDbCriteria creation, allowing MySQL to do the heavy lifting so it will run quicker. 现在编写第2版,我的目标是专注于聪明的CDbCriteria创建,允许MySQL进行繁重的工作,以便更快地运行。 The implementation is trivial when dealing with a single database table. 在处理单个数据库表时,实现是微不足道的。 The difficulty arises when I'm dealing with 2 or more tables... For example, if the user intends to search on a field that is a STAT relation, I need that relation to be present in my query so that I may include comparisons. 当我处理2个或更多表时出现困难...例如,如果用户想要搜索STAT关系的字段,我需要在我的查询中出现该关系,以便我可以包括比较。

Here's the question. 这是问题所在。 How do I assure that Yii includes all with relations in my query so that I include comparisons? 如何保证Yii的包括所有with我的查询中的关系,使我有比较? I've included all my relations with my criteria in the model's search function and I've tried CDbCriteria's together set to true ... 我已经在模型的search功能中包含了我的所有关系with条件,并且我已经尝试将CDbCriteria together设置为true ...

public function search() {
    $criteria=new CDbCriteria;
    $criteria->compare('id', $this->id);
    $criteria->compare( ...
    ...
    $criteria->with = array('relation0','relation1','relation3');
    $criteria->together = true;

    return new CActiveDataProvider(
        get_class($this), array(
            'criteria'=>$criteria,
            'pagination' => array('pageSize' => 50)
));}

Then I'll snatch the criteria from the DataProvider and add a few conditions , for example, looking for dates > 1234567890. But I still get errors like this... 然后我将从DataProvider中抢夺条件并添加一些条件 ,例如,查找日期> 1234567890.但我仍然会收到这样的错误...

CDbCommand failed to execute the SQL statement: 
SQLSTATE[42S22]: Column not found: 1054 Unknown column 't.relation3' in 'where clause'. 
The SQL statement executed was: 
SELECT COUNT(DISTINCT `t`.`id`) FROM `table` `t` 
LEFT OUTER JOIN `relation_table` `relation0` ON (`t`.`id`=`relation0`.`id`) 
LEFT OUTER JOIN `relation_table` `relation1` ON (`t`.`id`=`relation1`.`id`) 
WHERE (`t`.`relation3` > 1234567890)

Where relation0 and relation1 are BELONGS_TO relations, but any STAT relations, here depicted as relation3 , are missing. 其中relation0relation1BELONGS_TO关系,但缺少任何STAT关系,此处描述为relation3 Furthermore, why is the query a SELECT COUNT(DISTINCT 't'.'id') ? 此外,为什么查询是SELECT COUNT(DISTINCT 't'.'id')

Edit @DCoder Here's the specific relation I'm working with now. 编辑 @DCoder这是我现在正在使用的具体关系。 The main table is Call, which has a HAS_MANY relation to CallSegments, which keeps the times. 主表是Call,它与HAS_MANYHAS_MANY关系,可以保持时间。 So the startTime of the Call is the minimum start_time of all the related CallSegments. 因此,Call的startTime是所有相关CallSegments的最小start_time。 And startTime is the hypothetical relation3 in my anonymized query error. startTime是我匿名查询错误中的假设relation3

'startTime' => array(self::STAT, 'CallSegments', 'call_id',
            'select' => 'min(`start_time`)'),

Edit Other people have sent me to CDbCriteria's together property , but as you can see above, I am currently trying that to no avail. 编辑其他人已经把我送到了CDbCriteria的together财产 ,但正如你在上面所看到的,我目前正在尝试这一点无济于事。

Edit Looks like the issue has may have been reported: Yii and github tickets. 编辑貌似问题可能已经报告 Yii的GitHub的门票。

It is not a good idea to snatch the sql from a criteria and use it by yourself. 从标准中抢夺sql并自行使用它并不是一个好主意。

If you are using the "with" property then you could easily use comparisons like: 如果您使用“with”属性,那么您可以轻松地使用如下比较:

$criteria->compare("`relation1`.`id`", $yourVarHere);

Also Yii doesn't behave well with grouping. Yii在分组方面也表现不佳。

My approach with STAT relations is using an subquery in the selects of Yii, followed by having: 我与STAT关系的方法是在Yii的选择中使用子查询,然后是:

$criteria->select = array("`t`.*", "(SELECT COUNT(*) FROM `relation3` WHERE `id` = `t`.id_relation3) AS `rel3`");
$criteria->having = "`rel3` > " . $yourValue;

The above method creates a bug in the gridview pagination because the count is done on a different query. 上面的方法在gridview分页中创建了一个错误,因为计数是在不同的查询上完成的。 A workaround will be to drop the "with" property and write the joins by yourself in the "join" property like: 解决方法是删除“with”属性并在“join”属性中自行编写连接,如:

$criteria->join = "LEFT OUTER JOIN `relation_table` `relation0` ON (`t`.`id`=`relation0`.`id`) 
LEFT OUTER JOIN `relation_table` `relation1` ON (`t`.`id`=`relation1`.`id`)
LEFT OUTER JOIN `relation_table` `relation3` ON (`t`.`id`=`relation3`.`id`)";

If the bug is a little difficult to get working could you use the stat relation as a simple HAS_ONE with : 如果bug有点难以开始工作,你可以使用stat关系作为简单的HAS_ONE:

'select'=>'count(relation3.id)', 
'joinType'=>'left join',
'group'=>'relation3.id',
'on'=>'t.id = relation3.id',
'together'=>true

to get the count value out along side everything else? 将计数值与其他所有东西一起排除?

Not sure how well this would work for your case but it's been helpful for me from time to time. 不确定这对你的情况有多好,但它不时对我有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM