В Yii существует ли способ проверки табличного ввода с помощью CActiveForm?

ситуация

Я использовал статью wiki на сайте Yii, собирая табличный вход , чтобы следовать примеру.

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

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

У меня есть одна модель, ImportParseForm расширенная от CFormModel . У этого действительно есть только одно правило:

 public function rules() { return array( array('header', 'required'), ); } 

Вот фрагмент моего представления:

 <?php foreach($headers as $h => $hItem): ?> <div class="row"> <?php echo CHtml::label(CHtml::encode($hItem), "[$h]header"); ?> maps to <?php echo $fParse->textField($mForm, "[$h]header"); ?> <?php echo $fParse->error($mForm, "[$h]header"); ?> </div> <?php endforeach; ?> 

Вот фрагмент моего контроллера:

  $mForm = new ImportParseForm; $valid = true; if (isset($_POST['ImportParseForm'])){ foreach ($headers as $h => $hVal){ if (isset($_POST['ImportParseForm'][$h])){ $mForm->attributes = $_POST['ImportParseForm'][$h]; $valid = $mForm->validate() && $valid; } } if ($valid){ // Process CSV } } 

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

В Yii 1.1.10 они добавили CActiveForm :: validateTabular () , но похоже, что это для нескольких моделей. Не совсем то, что у меня здесь. Но для ударов я добавил следующее к моему контроллеру (конечно, удалил другой тип проверки):

 CActiveForm::validateTabular($mForm, array('header')); 

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

Вопрос

В принципе, могу ли я использовать CActiveForm для проверки правильности генерируемых динамических полей (аналогично табличному вводу, но только с одной моделью)?

После чтения « Сбор табличных входов» немного ближе, я использую «несколько» моделей. Я неправильно понял, что несколько моделей будут означать несколько разных структурированных моделей, а не только кратную одной и той же структурированной модели в массиве. Например, в вики есть часть, которая показывает, какие элементы (массив моделей) обновляется: $items=$this->getItemsToUpdate(); , Мое исправленное предположение состоит в том, что этот конкретный метод захватывает несколько одинаковой структурированной модели, но с разными первичными ключами … или разными записями. Понимая это, остальная часть статьи имеет больше смысла;)

Но вот мое модельное решение о том, как создать форму сопоставления заголовков CSV.

 class ImportParseForm extends CFormModel{ // Model really only has one attribute to check against, the header var $header; // New attributeLabels collected and stored on class instantiation protected $attributeLabels; // Modify construct so we can pass in custom attribute labels public function __construct($attributeLabels = '', $scenario = '') { if (! is_array($attributeLabels)){ $this->attributeLabels = array($attributeLabels); } else{ $this->attributeLabels = $attributeLabels; } parent::__construct($scenario); } public function rules() { return array( array('header', 'required'), ); } public function attributeLabels() { // Default mapping $arr = array( 'header' => 'Header Mapping', ); // Merge mapping where custom labels overwrite default return array_merge($arr, $this->attributeLabels); } } 

Вот фрагмент моего контроллера, на котором мой эквивалент $items=$this->getItemsToUpdate(); (опять же, цель состоит в том, чтобы собрать массив моделей) будет выглядеть

  // Get the first row of CSV, assume it's the headers $tmpCsvRow = explode("\n", $mTmp->data); $headers = explode(',', $tmpCsvRow[0]); foreach ($headers as $header){ if (! empty($header)){ // Blank headers are lame, skip them // Add a new model for each CSV header found into $mForm array // You can also add in a custom attributeLabel, $header is an actual header name like 'First Name', // so the new label for the header attribute in ImportParseForm would be 'First Name header' and // it will show up properly in your CActiveForm view $mForm[] = new ImportParseForm(array('header' => $header.' header')); } } 

Нажимайте $mForm для просмотра. Теперь, на ваш взгляд, итерации через $mForm для вашей формы, как это (похоже на статью wiki, но я использую виджет CActiveForm здесь):

 <?php foreach($mForm as $m => $mItem): ?> <div class="row"> <?php echo $fParse->labelEx($mItem,"[$m]header"); ?> maps to <?php echo $fParse->textField($mItem, "[$m]header"); ?> <?php echo $fParse->error($mItem, "[$m]header"); ?> </div> <?php endforeach; ?> 

Валидация работает должным образом.

Если вы хотите использовать проверку AJAX, используйте CActiveForm::validateTabular() в вашем контроллере (вместо обычного validate() ).

Надеюсь, это поможет другим начинающим Yii! 🙂

Я пытался сделать подобное, и это мое решение в случае формы обновления модели. Здесь я использовал проверку модели для атрибутов модели обновления в событии изменения стоимости, которому не нужна кнопка отправки, и выглядит просто и причудливо. Вот фрагмент кода …

просмотреть код:

  <?php foreach($modelArray as $model): ?> <div class="row"> <?php echo $form->textField($model, "[$model->id]attributeName"); ?> <?php echo $form->label($model, "[$model->id]attributeName"); ?> <?php echo $form->error($model, "[$model->id]attributeName"); ?> </div> <?php endforeach; ?> 

код контроллера:

  objArray = array(); foreach($_REQUEST['ModelName'] as $id => $attributes){ $obj = ModelName::model()->findByPk($id); $obj->attributes = $attributes; $obj->save(); $objArray[$id] = $obj; } echo CActiveForm::ValidateTabular($objArray); Yii::app()->end();