Yii динамическое количество столбцов

Вот я подготовил начальный проектик ссылка
Делал на основании
Вход admin\admin gii - root

База - mysql localhost:locadb
Вид минимальной базы под действия
Что мы хотим получить

то есть в зависимости от шаблона (таблица template) мы отображаем разные столбцы (из таблицы element берем имена, из таблицы analiz_has_element значения)

создаем базу https://github.com/des1roer/yii_heart/blob/master/basesql.sql

создаем модели и CRUD под все таблицы (под template_has_elem crud можно не создавать).
 
тогда в
  • ...\yiiHeart\protected\extensions\heart\views\layouts\_menu.php 
можем добавить
    array('label' => 'Проект',
    'url' => '#',
    'icon' => 'fa fa-sitemap',
  
    'items' => array(
   array('label' => 'template',
    'url' => array('/template'),
    'icon' => 'fa fa-info'),
    array('label' => 'analiz',
    'url' => array('/analiz'),
    'icon' => 'fa fa-info'),
    array('label' => 'element',
    'url' => array('/element'),
    'icon' => 'fa fa-info', ),
    array('label' => 'has_element',
    'url' => array('/haselement'),
    'icon' => 'fa fa-info'),
    array('label' => 'template_has',
    'url' => array('/templatehas'),
    'icon' => 'fa fa-info')

)),

получаем

выводим все элементы в ...\yiiHeart\protected\views\template\_form.php
findAll(), 'id', 'name');

if (isset($model->id))
{
    $arr = HasElement::model()->findAll("template_id=:id", array(':id' => $model->id));
}

if (isset($arr))
{
    for($i = 0; $i < count($arr); $i++)
    {                    
        $arr_bit[] = $arr[$i]->element_id;
    }
}
else
    $arr_bit = array();

// $data = CHtml::textField('textField'); 
echo CHtml::checkBoxList('im_id2', $arr_bit, $type_list, array(
    'template' => "{input} {labelTitle}",
    'class' => 'chclass',
    'labelOptions'=>array('style'=>'display:inline'),
        )
);
//просто рисуем чекбокслитс из базы
//данные для элементов
?>  

-
получаем 
в контролере прописываем
при создании

if (isset($_POST['im_id2']))
{
    $command = Yii::app()->db->createCommand();
    $max = Yii::app()->db->createCommand()
            ->select('COALESCE ((max(id)), 1) as max')
            ->from('template')
            ->queryScalar();

    foreach($_POST['im_id2'] as $check)
    {
        $Ids = $_POST['im_id2'];
    };
    for($i = 0; $i < count($Ids); $i++)
    {
        $command->insert('template_has_element', array(
            'template_id' => $max, ////
            'element_id' => (int) $Ids[$i], ////
        ));
    }
};

при изменении

if (isset($_POST['im_id2']))
{
   $command = Yii::app()->db->createCommand();
   $command->delete('template_has_element', 'template_id=:id', array(':id' => $model->id));
   foreach($_POST['im_id2'] as $check)
   {
       $Ids = $_POST['im_id2'];
   };
   for($i = 0; $i < count($Ids); $i++)
   {
       $command->insert('template_has_element', array(
           'template_id' => $model->id, ////
           'element_id' => (int) $Ids[$i], ////
       ));
   }
};  


все как здесь

ввод анализа
в ...\yiiHeart\protected\views\analiz\_form.php
дописываем

//добавление данных для ввода (при создании новой записи и отсутствии записи в изменяемой)
$id_template = $model->template_id;
if (isset($id_template))
{
    $connection = Yii::app()->db;
    if (isset($model->id))
    {
        $id2 = $model->id;
        $sql2 = "
            SELECT dat.`element_id` AS id,
                   dat.`value` AS value,
                   `el`.`name` AS name
            FROM `analiz_has_element` dat,
                 `element` el
            WHERE `analiz_id` = $id2
              AND el.id=dat.`element_id`
                            ";
        $dataReader2 = $connection->createCommand($sql2)->query();
        $rows2 = $dataReader2->readAll();
        for($i = 0, $cnt = count($rows2); $i < $cnt; $i++)
        {
            $id = $rows2[$i]['id'];
            echo CHtml::label($rows2[$i]['name'], $rows2[$i]['name']);
            echo CHtml::textField("elem[$id][val]", $rows2[$i]['value'], array('id' => $rows2[$i]['name']));
            $condition .= ' AND temp.`element_id` != ' . $id;
        }
    }
    (isset($condition) && $condition) ? '' : $condition = null;
    $sql = "
            SELECT temp.`element_id` as id,
                   el.`name` as name
            FROM `template_has_element` TEMP,
                                        `element` el
            WHERE `template_id` = $id_template
              AND `temp`.`element_id` = el.`id`
              $condition 
                            ";
    $dataReader = $connection->createCommand($sql)->query();
    $rows = $dataReader->readAll();

    for($i = 0, $cnt = count($rows); $i < $cnt; $i++)
    {
        $id = $rows[$i]['id'];
        echo CHtml::label($rows[$i]['name'], $rows[$i]['name']);
        echo CHtml::textField("elem[$id][val]", '', array('id' => $rows[$i]['name']));
    }
}

таким образом в зависимости от шаблона у раз разное число полей для ввода.
тогда по аналогии в контроллере при создании

if (isset($_POST['elem']))
{
    $command = Yii::app()->db->createCommand();
    $max = Yii::app()->db->createCommand()
            ->select('COALESCE ((max(id)), 1) as max')
            ->from('analiz')
            ->queryScalar();

    $Ids = $_POST['elem'];
    //echo '<pre><hr />';
    $cnt = max(array_keys($Ids));
    $min = min(array_keys($Ids));
    for($i = $min; $i <= $cnt; $i++)
    {
        $val = $Ids[$i]['val'];
        //echo $Ids[$i]['per'][0];
        if (isset($val) && !empty($val))
            $command->insert('analiz_has_element', array(
                'analiz_id' => $max, ////
                'value' => $val,
                // 'f_precision' =>  $Ids[$i]['per'][0], 
                'element_id' => $i
            ));
    }
};

при обновлении

if (isset($_POST['elem']))
 {
     $command = Yii::app()->db->createCommand();
     $command->delete('analiz_has_element', 'analiz_id=:id', array(':id' => $model->id));
     $Ids = $_POST['elem'];
     //echo '
';
     $cnt = max(array_keys($Ids));
     $min = min(array_keys($Ids));
     for($i = $min; $i <= $cnt; $i++)
     {
         $val = $Ids[$i]['val'];
         if (isset($val) && !empty($val))
             $command->insert('analiz_has_element', array(
                 'analiz_id' => $model->id, ////
                 'value' => $val,
                 'element_id' => $i
             ));
     }
 };

ну и отображение в ...\yiiHeart\protected\views\analiz\admin.php

db->createCommand()
            ->select('value')
            ->from('analiz_has_element')
            ->where("analiz_id=$analiz_id"
                    . " and element_id = $elem_id")
            ->queryScalar();
        return (isset($num)) ? $num : '';
}
$myarray[] = array('header'=>'No','value'=>'($this->grid->dataProvider->pagination->currentPage*
      $this->grid->dataProvider->pagination->pageSize
     )+ ($row+1)',
    'htmlOptions' => array('style' =>'width: 25px; text-align:center;'),
  );
$myarray[] =    array(
     //     'header' => 'Name',
          'name'=> 'name',
          'type'=>'raw',
          'value' => '($data->name)',
          'class' => 'bootstrap.widgets.TbEditableColumn',
             'headerHtmlOptions' => array('style' => 'text-align:center'),
    'editable' => array(
     'type'    => 'textarea',
     'url'     => $this->createUrl('editable'),
     'params' => array('YII_CSRF_TOKEN' => Yii::app()->request->csrfToken),
    )
  );

$template = 11;
//находим все элементы из шаблона 
$connection = Yii::app()->db;
$sql = "
        SELECT te.`element_id`,
               el.name
        FROM `template_has_element` `te`,
             `element` el
        WHERE el.id= te.`element_id`
          AND te.`template_id`=$template
                            ";
$dataReader = $connection->createCommand($sql)->query();
$rows = $dataReader->readAll();


/* -----------------Данные для таблицы------------------------------------------- */

  for($i = 0, $cnt = count($rows); $i < $cnt; $i++) //формируем столбцы
  {
  $id = $rows[$i]['element_id'];
  $myarray[] = array(
  'header' =>  $rows[$i]['name'], 
  'id' => $id,
  'value' => 'num($data->id,'.$id.')',
  'htmlOptions' => array('style' => 'width: 15px; text-align:center;'),
  'headerHtmlOptions' => array('style' => 'text-align:center'),
  );
  }

$myarray[] = array(
    'class' => 'bootstrap.widgets.TbButtonColumn',
    'buttons' => array
        (
        'view' => array
            (
            'url' => '$data->id."|".$data->name',
            'click' => 'function(){
                  data=$(this).attr("href").split("|")
                  $("#myModalHeader").html(data[1]);
            $("#myModalBody").load("' . $this->createUrl('view') . '&id="+data[0]+"&asModal=true");
                  $("#myModal").modal();
                  return false;
                 }',
        ),
    )
);
$this->widget('bootstrap.widgets.TbGridView',array(
 'id'=>'analiz-grid',
 'dataProvider'=>$model->search(),
 'filter'=>$model,
 'type' => 'striped hover', //bordered condensed
 'columns'=>$myarray, 
)); ?>

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

код наверно не идеальный, советы и замечания прошу оставлять в комментах. рабочий код лежит в проекте на гитхаб(ссылка самая первая)

Комментарии

Популярные сообщения из этого блога

Пишем логи на C# (.NET). Легкий способ.

Средства для работы с базой данный PostgreSql