Вывод таблицы CGridView

Здравствуйте!

Прошу помощи новичку в yii.

Есть 2 таблицы - tbl_auto(авто) и tbl_file(файлы), связаны между собой 3-ей таблицей, названной tbl_model_file.

Т.е. каждое авто содержит множество уникальных файлов (уникальных - значит один файл может быть в разных авто).

Как вывести следующую таблицу (скорее всего через CArrayDataProvider и виджета CGridView) с фильтрацией и сортировкой по авто со следующими строками таблицы:

  • Авто 1

  • Чертеж к авто 1 №1

  • Чертеж к авто 1 №2

  • Чертеж к авто 1 №N

  • Авто 2

  • Чертеж к авто 2 №1

  • Чертеж к авто 2 №2

  • Чертеж к авто 2 №N

  • Авто N

  • Чертеж к авто N №1

  • Чертеж к авто N №2

  • Чертеж к авто N №N

?

Зачем CArrayDataProvider если с это все можно реализовать с помощью CActiveDataProvider?

Если я правильно понимаю то сначала в модели таблицы tbl_auto нужно указать реляцию


    

public function relations() {

  return array(

    'modelFiles' => array(self::MANY_MANY, 'File', 'tbl_model_file(id_auto, if_file)'),

  );

}



Потом создал бы в модели машин следующее:




    public function search() {

        $criteria = new CDbCriteria;

        $criteria->with = array('modelFiles');

        $criteria->together = true;


        $criteria->compare('t.id_auto', $this->id_auto);

        $criteria->compare('modelFiles.id_file', $this->id_file);


        return new CActiveDataProvider($this, array(

            'criteria' => $criteria

        ));

    }



Сортировка будет и по файлам, ну а вдруг :) тогда надо в модели машин прописать ещё:




public $id_file



и в rules модели внести её.

Ну и теперь вызвать все это в контроллере:




        $model = new Auto('search');

        $model->unsetAttributes();


        if (isset($_GET['Auto'])) {

            $model->attributes = $_GET['Auto'];

        }

        $this->render('index', array(

            'model' => $model,

        ));



И вьюха:




<?php

$this->widget('zii.widgets.grid.CGridView', array(

    'dataProvider' => $model->search(),

    'filter' => $model,

    'columns' => array(

        array(

            'name' => 'id_auto',

            'type' => 'raw',

            'value' => '$data->name_auto',

            'filter' => CHtml::dropDownList('Auto[id_auto]', 

                 $this->id_auto, CHtml::ListData(Auto::model()->findAll(), 'id_auto', 'name_auto'),

                 array('empty'=>'Все')),

        ),

        array(

            'name' => 'id_file',

            'type' => 'raw',

            'value' => '$data->getRelatedFiles()',

            'filter' => CHtml::dropDownList('Auto[id_file]', 

                 $this->id_file, CHtml::ListData(File::model()->findAll(), 'id_file', 'name_file'),

                 array('empty'=>'Все')),

        )

    ),

    ));

?>



Ну ещё теперь в модели надо будет добавить следующее:




    public function getRelatedFiles() {

        $arr = array();

        foreach ($this->modelFiles as $file){

            $arr[] = $file->name_file;

        }

        return implode(',<BR>', $arr);

    }



Возможно будет выводить по 1 файлу, тогда надо будет чуть переделать функцию, попробуй пока так.

Ещё проверь названия полей и моделей, писал свои т.к. твою структуру таблиц я не знаю.

Если все же заработает тогда надо будет переделать вывод значений для dropDown в гриде, findAll не очень вариант :)

Спасибо большое! Попробовал - получилось, только фильтрация и сортировка файлов не работает…но это я уж как нибудь сам.

И получается отдельными строками в таблице файлы нельзя сделать?

Т.е. сейчас идет строка с авто и в ней же список чертежей, а хотелось бы ещё так, чтобы строка авто, а за ней строки с файлами.

Ну задача была сделать в 1 строке авто, а в другой её чертежи, я так её понял, а ты хочешь чтоб было не так:

Авто 1 - Чертеж 1, Чертеж 2

Авто 2 - Чертеж 1, Чертеж 2

А вот типо такого:

Авто 1 - Чертеж 1

Авто 1 - Чертеж 2

Авто 2 - Чертеж 1

Авто 2 - Чертеж 2

Я правильно понял?

Для сортировки надо смотреть как у тебя в модели все прописано, мб в rules не указаны поля или ещё что, так сказать не могу не глядя.

Почти, я хочу чтобы было вот так:

строка №1 - Авто 1

строка №2 - Чертеж 1

строка №3 - Чертеж 2

строка №4 - Авто 2

строка №5 - Чертеж 1

строка №6 - Чертеж 2 и т.д.

Получается разумнее чтобы Авто и Чертеж были в разных столбцах таблицы.

С сортировкой и фильтрации тогда пока попозже.

Так тебе и таблица думаю не надо, может списком сделать все? Будет что-то вроде такого:

<div class="block">

Авто 1

Чертеж 1

Чертеж 2

</div>

<div class="block">

Авто 2

Чертеж 1

Чертеж 2

</div>

Чертежы те которые к авто относятся я так понял, списком сойдет? Тогда напишу кусок кода для такого варианта

Только таблицей, т.к. там ещё идет колонка "Дата создания"

Вроде бы я тебя понял, у тебя выходит будет 2 поля, в 1 будет Авто и ниже его чертежы, в другом дата создания?

Тогда тебе нужно просто не много изменить код:

В модели сделаем так:




public function getAutoWithRelatedFiles() {

        $arr[] = $this->name_auto;

        foreach ($this->modelFiles as $file){

            $arr[] = $file->name_file;

        }

        return implode(',<BR>', $arr);

    }



И в гриде:




<?php

$this->widget('zii.widgets.grid.CGridView', array(

    'dataProvider' => $model->search(),

    'filter' => $model,

    'columns' => array(

        array(

            'name' => 'id_auto',

            'type' => 'raw',

            'value' => '$data->getAutoWithRelatedFiles()',

            'filter' => CHtml::dropDownList('Auto[id_auto]', 

                 $this->id_auto, CHtml::ListData(Auto::model()->findAll(), 'id_auto', 'name_auto'),

                 array('empty'=>'Все')),

        ),

        'created'

    ),

    ));

?>



created - это поле в таблице в котором хранится дата, если у тебя она в timestamp или просто хочешь изменить внешний вид тогда нужно следующее сделать:




    'columns' => array(

        array(

            'name' => 'id_auto',

            'type' => 'raw',

            'value' => '$data->getAutoWithRelatedFiles()',

            'filter' => CHtml::dropDownList('Auto[id_auto]', 

                 $this->id_auto, CHtml::ListData(Auto::model()->findAll(), 'id_auto', 'name_auto'),

                 array('empty'=>'Все')),

        ),

        array(

            'name' => 'created',

            'value' => 'date("d-m-Y", $data->created)',

        ),

    ),



Выходит слева будет вывод авто и ниже его чертежей, справа дата, следующей строкой новое авто и его чертежи, но как по мне лучше Авто отдельно и чертежи отдельно, в разных колонках, а то ничего не понятно как по мне, или я опять что-то не так понял:) Есть картинка как это должно выглядеть? Хотя бы в экселе

Прикрепил файл как должно быть. Голубые строки - это автомобили.

Я сделал так, как на изображении, но пришлось пойти следующим путем: в отдельный массив положить автомобили и в отдельный чертежи, объединить массивы и вывести при помощи CArrayDataProvider, но при таком способе невозможно сделать фильтрацию и сортировку, да и притом несколько коряво выглядит моё решение

Вот так куда понятней, ну я бы через CListView попробовал, конечно может не лучшее решение, но какое есть, приведу самый простой пример:

Сначала во вьюхе сделать так:




<table class="table-report hidden-xs">

   <thead>

      <th>Код изделия</th>

      <th>Тип файла</th>

      <th>Дата создания</th>

   </thead>

   <tbody>

   <?php

   $this->widget('zii.widgets.CListView', array(

       'id'=>'YOUR_ID',

       'dataProvider' => $model->search(),

       'itemView' => '_view',

   ));

   ?>

    </tbody>

</table>



В той же папке для вьюх контроллера создать файл _view.php:




<tr>

   <td><?php echo $data->name_auto;?></td>

   <td></td>

   <td><?php echo $data->created;?></td>

</tr>

<?php if (count($data->modelFiles) > 0): ?>  

    <tr>

       <?php foreach ($data->modelFiles as $file): ?>

       <td><?php echo $file->name_file;?></td>

       <td><?php echo $file->type_file;?></td>

       <td><?php echo $data->created;?></td>

       <?php endforeach; ?>

    </tr>

<?php endif; ?>



Если хочешь чеки и сворачивание тоже можно сделать, но это уже без меня :)

Сортировку как делать для CListView можешь найти в гугле, информации куча, не буду писать все, возможно можно и гридом все это делать, но мб с помощью YiiBooster, хотя сомневаюсь.

Ну и чтоб цвета разные были уже стили навешаешь, думаю все понятно описал.

А ну и можешь удалить с модели функцию для вывода реляции.

Классы только убери с таблицы, со своего проекта скопировал просто

Спасибо!

Всё работает как надо!

Сортировку сделал, с фильтрацией и остальным сам разберусь

Та не за что:)