И еще раз вопрос по CGridView, двум таблицам, и HAS_MANY

Общие вопросы по использованию фреймворка. Если не знаете как что-то сделать и это про Yii, вам сюда.
Ответить
Tiosteel
Сообщения: 2
Зарегистрирован: 2013.11.05, 10:14

И еще раз вопрос по CGridView, двум таблицам, и HAS_MANY

Сообщение Tiosteel »

Добрый день. Неделю назад начал изучать данный фреймворк. Появилось, как я понимаю, обычное желание найти рабочий пример по выводу нескольких значений какого-либо поля подчиненной таблицы в ячейку СGridView

есть таблица project (id, name, ...)
есть подчиненная ей таблица project_phone (id, id_project, phone, ...)

связи в классе project прописаны

Код: Выделить всё

public function relations()
{
    return array(
        'project_phone' => array(self::HAS_MANY, 'project_phone', 'id_project'),
    );
}
DataProvider получаю так:

Код: Выделить всё

$dataProvider = new CActiveDataProvider('project', array(
                'pagination' => array('pageSize' => 10),
                'criteria' => array(
                    'with'=>array('project_phone'),
                ),
            ));
во вьюхе пытаюсь вывести так:

Код: Выделить всё

$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider' => $dataProvider,
    'ajaxUpdate' => false,
    'columns' => array(
        array(
            'name' => 'id',
        ),
        array(
            'name' => 'name',
        ),
        array(
            'name' => 'timestamp_create',
            'value' => 'Yii::app()->dateFormatter->formatDateTime($data->timestamp_create);',
        ),
        array(
            'name' => 'timestamp_update',
            'value' => 'Yii::app()->dateFormatter->formatDateTime($data->timestamp_update);',
        ),
        array(
            'name' => 'project_phone.phone',
            'header' => project::model()->getAttributeLabel('project_phone'),
        ),
        array(
            'class' => 'CButtonColumn',
            'template' => '{update}',
        ),
    ),
));
поиск по форуму или гуглу не дал, к сожалению, внятных результатов

подобная конструкция у меня прекрасно работает для связей BELONGS_TO, когда родительская строка всего одна
вывод списка из подчиненной таблицы также сработал для формы редактирования через dropDownList + listData, но в данном случае интересует решение именно для ячейки CGridView

что нужно добавить?
Nafania
Сообщения: 1227
Зарегистрирован: 2011.01.31, 13:12

Re: И еще раз вопрос по CGridView, двум таблицам, и HAS_MANY

Сообщение Nafania »

Нужно добавить цикл, ведь у вас там массив, а не одно значение.
glamurchik
Сообщения: 65
Зарегистрирован: 2011.04.27, 21:39

Re: И еще раз вопрос по CGridView, двум таблицам, и HAS_MANY

Сообщение glamurchik »

и какое решение получилось?
Tiosteel
Сообщения: 2
Зарегистрирован: 2013.11.05, 10:14

Re: И еще раз вопрос по CGridView, двум таблицам, и HAS_MANY

Сообщение Tiosteel »

glamurchik писал(а):и какое решение получилось?
пронаследовал CDataColumn. Честно говоря, похоже на говнокод, но как уж есть

добавил несколько методов вывода массива, название которых заканчивается на Render,
в основном методе renderDataCellContent просто проверяется существование указанного Render-метода, и данные уже выводятся через него

пример вьюхи:

Код: Выделить всё

$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider' => $dataProvider,
    'ajaxUpdate' => false,
    'columns' => array(
        array(
            'name' => 'id',
        ),
        array(
            'name' => 'name',
        ),
        array(
            'name' => 'timestamp_create',
            'value' => 'Yii::app()->dateFormatter->formatDateTime($data->timestamp_create);',
        ),
        array(
            'name' => 'timestamp_update',
            'value' => 'Yii::app()->dateFormatter->formatDateTime($data->timestamp_update);',
        ),
        array(
            'name' => 'project_phone.phone',
            'class' => 'DLinkListColumn',
            'relationName' => 'project_phone',
            'relationField' => 'phone',
            'renderMethod' => 'simpleList'
        ),
        array(
            'name' => 'users.login',
            'class' => 'DLinkListColumn',
            'relationName' => 'users',
            'relationField' => 'login',
            'renderMethod' => 'simpleList'
        ),
        array(
            'class' => 'CButtonColumn',
            'template' => '{update}',
        ),
    ),
));
Унаследованный класс:

Код: Выделить всё

class DLinkListColumn extends CDataColumn
{
    public $renderMethod;
    public $relationName;
    public $relationField;
    public $limit;

    protected function simpleListRender($data, $row)
    {
        if (isset($row->{$this->relationName}) && is_array($row->{$this->relationName}))
        {
            foreach ($row->{$this->relationName} as $rowElem)
            {
                echo $rowElem->{$this->relationField}.'<br />';
            }
        }
    }

    protected function serializedArrayRender($data, $row)
    {
        if (isset($row->{$this->relationName}) && is_array($unserializedArray = @unserialize($row->{$this->relationName})))
        {
            $lim = (intval($this->limit) > 0) ? intval($this->limit) : count($unserializedArray);
            $i = 0;

            if ($lim > 0)
            {
                foreach ($unserializedArray as $rowKey => $rowElem)
                {
                    echo $rowKey.' => '. $rowElem.'<br />';
                    $i++;

                    if ($i >= $lim) break;
                }
            }
        }
    }

    protected function renderDataCellContent($data, $row)
    {
        if (method_exists($this, $this->renderMethod.'Render'))
        {
            $this->{$this->renderMethod.'Render'}($data, $row);
        }
        else
        {
            throw new ErrorException('this render method doesnt exists');
        }
    }
}
Тему пока оставлю открытой, не будет ответов пару дней - закрою
Аватара пользователя
yiijeka
Сообщения: 3103
Зарегистрирован: 2012.01.28, 09:14
Откуда: Беларусь
Контактная информация:

Re: И еще раз вопрос по CGridView, двум таблицам, и HAS_MANY

Сообщение yiijeka »

Да куча вариантов как это сделать. Вот вам один, на коленке набросал, вставляется в columns:

Код: Выделить всё

array(
                    'header' => 'Связанная табличка телефонов',
                    'type' => 'html',
                    'value' => function ($data) {
                            Yii::app()->getController()->widget(
                                'zii.widgets.grid.CGridView',
                                array('dataProvider' => new CArrayDataProvider($data->project_phone),
                                    'columns' => array(
                                        'phone'
                                    )
                                )
                            );
                        },
                ),
Есть куча сторонних расширений расширяющих возможности GridView - http://www.yiiframework.com/extensions/?tag=gridview и http://yiibooster.clevertech.biz/extend ... ridcolumns . Но как то я всегда выкручивался стандартным виджетом, т.к. сторонние позволяли писать просто вместо, например, кода выше, одну строку.
Последний раз редактировалось yiijeka 2013.11.06, 09:41, всего редактировалось 1 раз.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: И еще раз вопрос по CGridView, двум таблицам, и HAS_MANY

Сообщение ElisDN »

Код: Выделить всё

'value'=>'implode(", ", CHtml::listData($data->project_phone, "id", "phone"))',
Ответить