简体   繁体   English

在Yii中使用CArrayDataProvider过滤CGridView:怎么样?

[英]Filtering CGridView with CArrayDataProvider in Yii: how?

I created a CGridView in Yii whose rows are read from an XML file. 我在Yii中创建了一个CGridView,其行从XML文件中读取。 I'm not using any models: only a controller (where I read the file) and a view (where I display the grid). 我没有使用任何模型:只有一个控制器(我在那里读取文件)和一个视图(我在哪里显示网格)。 What I cannot create is a filter (one input field per column) in the first row of the grid so to visualize only certain rows. 我无法创建的是网格第一行中的过滤器(每列一个输入字段),以便仅显示某些行。 How can I do it? 我该怎么做?

This is what I have until now: 这就是我现在所拥有的:

Controller: 控制器:

<?php
class TestingController extends Controller {
    public function actionIndex() {
        $pathToTmpFiles = 'public/tmp';
        $xmlResultsFile = simplexml_load_file($pathToTmpFiles.'/test.xml');
        $resultData = array();
            foreach ($xmlResultsFile->result as $entry) {
                $chromosome = $entry->chromosome;
                $start = $entry->start;
                $end = $entry->end;
                $strand = $entry->strand;
                $crosslinkScore = $entry->crosslinkScore;
                $rank = $entry->rank;
                $classification = $entry->classification;
                $mutation = $entry->mutation;
                $copies = $entry->copies;
                array_push($resultData, array('Chromosome'=>$chromosome, \
                    'Start'=>$start,  'End'=>$end, Strand'=>$strand, \
                    'Crosslink_Score'=>$crosslinkScore,'Rank'=>$rank, \
                    'Classification'=>$classification, 'Mutation'=>$mutation, \
                    'Copies'=>$copies));
        }
        $this->render('index', array('resultData' => $resultData));
    }
}
?>

View: 视图:

<?php
$dataProvider = new CArrayDataProvider($resultData, \
    array('pagination'=>array('pageSize'=>10,),));

$this->widget('zii.widgets.grid.CGridView', array( 'id' => 'mutationResultsGrid',
    'dataProvider' => $dataProvider, 'columns' => array(
        array(
           'name' => 'Chromosome',
           'type' => 'raw',
       ),
       array(
           'name' => 'Start',
           'type' => 'raw',
       ),
       array(
           'name' => 'End',
           'type' => 'raw',
       ),
       array(
           'name' => 'Strand',
           'type' => 'raw',
       ),
       array(
           'name' => 'Crosslink_Score',
           'type' => 'raw',
       ),
       array(
           'name' => 'Rank',
           'type' => 'raw',
       ),
       array(
           'name' => 'Classification',
           'type' => 'raw',
       ),
       array(
           'name' => 'Mutation',
           'type' => 'raw',
       ),
       array(
           'name' => 'Copies',
           'type' => 'raw',
       ),
    ),
));
?>

Thanks for your help Ale 谢谢你的帮助Ale

file: FiltersForm.php (I put it in components folder) file: FiltersForm.php (我把它放在components文件夹中)

/**
 * Filterform to use filters in combination with CArrayDataProvider and CGridView
 */
class FiltersForm extends CFormModel
{
    public $filters = array();

    /**
     * Override magic getter for filters
     */
    public function __get($name)
    {
        if(!array_key_exists($name, $this->filters))
            $this->filters[$name] = null;
        return $this->filters[$name];
    }

    /**
     * Filter input array by key value pairs
     * @param array $data rawData
     * @return array filtered data array
     */
    public function filter(array $data)
    {
        foreach($data AS $rowIndex => $row) {
            foreach($this->filters AS $key => $value) {
                // unset if filter is set, but doesn't match
                if(array_key_exists($key, $row) AND !empty($value)) {
                    if(stripos($row[$key], $value) === false)
                        unset($data[$rowIndex]);
                }
            }
        }
        return $data;
    }
}

In your controller : 在你的控制器中

...
$filtersForm = new FiltersForm;
if (isset($_GET['FiltersForm'])) {
    $filtersForm->filters = $_GET['FiltersForm'];
}
$resultData = $filtersForm->filter($resultData);

$this->render('index', array(
    'resultData' => $resultData,
    'filtersForm' => $filtersForm
)}//end action

And last what need - add filters to CGridView config array: 最后需要 - 为CGridView配置数组添加过滤器:

...
'dataProvider' => $dataProvider,
'enableSorting' => true,
'filter' => $filtersForm,
...

Why don't you store the information from the xml to a database and use YII ActiveRecord? 为什么不将xml中的信息存储到数据库并使用YII ActiveRecord?

In your case you would need a live mechanism to filter the resultset on every filter query. 在您的情况下,您需要一个实时机制来过滤每个筛选查询的结果集。 Like with the search() method, when you use YII ActiveRecord models. 与search()方法一样,当您使用YII ActiveRecord模型时。

So you could use something like array_filter() with callback on your array on every filter call. 所以你可以在每个过滤器调用上使用像array_filter()这样的东西在你的数组上使用回调。 (Edit: or the mechanism used here with stripos to return the matching "rows": Yii Wiki ) (编辑:或此处使用stripos的机制返回匹配的“行”: Yii Wiki

Or, second option, you could make the xml parser dependend on your filter inputs, which does not feel good to me :). 或者,第二个选项,您可以使xml解析器依赖于您的过滤器输入,这对我来说不太好:)。 The parser would habe to parse on every filter input, which could be a problem with big xml files. 解析器可以解析每个过滤器输入,这可能是大xml文件的问题。

Or, as mentioned, save the information to the database and use standard YII mechanisms. 或者,如上所述,将信息保存到数据库并使用标准YII机制。

Assuming you can use the data obtained in the objects in your foreach loop as the filter for that particular column, you could then pass these values through to the view, something like: 假设您可以将foreach循环中对象中获得的数据用作该特定列的过滤器,则可以将这些值传递给视图,例如:

<?php
class TestingController extends Controller {
    public function actionIndex() {
        $pathToTmpFiles = 'public/tmp';
        $xmlResultsFile = simplexml_load_file($pathToTmpFiles.'/test.xml');
        $resultData = array();
        foreach ($xmlResultsFile->result as $entry) {
            ...
            $chromosomeFilter[] = $entry->chromosome;
            ...
        }
        $this->render('index', array(
            'resultData'       => $resultData,
            'chromosomeFilter' => $chromosomeFilter,
            ...
        );
    }
}
?>

And then use that value in the filter for that column; 然后在该列的过滤器中使用该值;

...
array(
    'name'   => 'Chromosome',
    'type'   => 'raw',
    'filter' => $chromosomeFilter,
),
...

I've not tested, and it depends a lot on the structure of your xml and $entry->chromosome , but that might help put you on the right path? 我没有测试过,这很大程度上取决于你的xml和$entry->chromosome ,但这可能有助于你走上正确的道路?

I had the same problem and what I did was I implement http://www.datatables.net/ And pull the data remotely . 我有同样的问题,我做的是我实施http://www.datatables.net/并远程拉取数据。 I pass the sorting and pagination to javascript . 我将排序和分页传递给javascript。

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

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