在 Yii 中,有没有办法使用 CActiveForm 验证表格输入? [英] In Yii, is there a way to validate tabular input with CActiveForm?

查看:23
本文介绍了在 Yii 中,有没有办法使用 CActiveForm 验证表格输入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

情况

我使用了 Yii 网站上的维基文章,收集表格输入,以如下为例.

我不认为我需要针对多个模型验证传统意义上的表格输入.我只有一个模型,但我正在动态创建表单中的字段数.这里有更多背景信息.

我正在导入 CSV 文件,其中的标题在不同文件中的顺序不同.在正确解析文件之前,用户需要映射哪个标题将映射到哪个表/列.

我有一个模型,ImportParseFormCFormModel 扩展而来.它实际上只有一个规则:

公共函数规则(){返回数组(数组('标题','必需'),);}

以下是我的观点:

 $hItem): ?><div class="row"><?php echo CHtml::label(CHtml::encode($hItem), "[$h]header");?>映射到<?php echo $fParse->textField($mForm, "[$h]header");?><?php echo $fParse->error($mForm, "[$h]header");?>

<?php endforeach;?>

这是我的控制器的一个片段:

 $mForm = new ImportParseForm;$有效 = 真;如果 (isset($_POST['ImportParseForm'])){foreach ($headers as $h => $hVal){if (isset($_POST['ImportParseForm'][$h])){$mForm->attributes = $_POST['ImportParseForm'][$h];$valid = $mForm->validate() &&$有效;}}如果($有效){//处理CSV}}

如果所有字段都有效,则按预期通过.问题是如果其中一个字段无效(或者在这种情况下为空),则所有字段都被标记为无效.

在 Yii 1.1.10 中,他们添加了 CActiveForm::validateTabular(),但看起来它适用于多个模型.不完全是我在这里.但是为了踢球,我在控制器中添加了以下内容(当然删除了其他类型的验证):

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

表单本身只有在填充第一个元素时才有效.如果第一个元素被填充,它会将所有其他元素设置为相同的值(并通过验证).

问题

基本上,我可以使用 CActiveForm 对动态生成的字段进行验证吗(类似于表格输入,但只有一个模型)?

解决方案

阅读后 收集表格输入 更近一点,我正在使用多个"模型.我误解了多个模型意味着多个不同的结构化模型,而不仅仅是数组中相同结构化模型的多个.例如,在 wiki 中有一段显示要更新哪些项目(模型数组):$items=$this->getItemsToUpdate();.我更正的假设是该特定方法获取多个相同结构化模型但具有不同的主键......或不同的记录.理解了这一点,文章的其余部分就更有意义了 ;)

但这是我关于如何创建 CSV 标头映射表单的模型解决方案.

class ImportParseForm 扩展 CFormModel{//模型实际上只有一个要检查的属性,即标题var $header;//收集并存储在类实例化中的新属性标签受保护的 $attributeLabels;//修改构造,以便我们可以传入自定义属性标签公共函数 __construct($attributeLabels = '', $scenario = ''){if (!is_array($attributeLabels)){$this->attributeLabels = array($attributeLabels);}别的{$this->attributeLabels = $attributeLabels;}parent::__construct($scenario);}公共函数规则(){返回数组(数组('标题','必需'),);}公共函数attributeLabels(){//默认映射$arr = 数组('标题' =>'标题映射',);//合并映射,其中自定义标签覆盖默认值返回 array_merge($arr, $this->attributeLabels);}}

这是我的控制器中的一个片段,与 $items=$this->getItemsToUpdate();(同样,目标是收集模型数组)的等价物看起来像

//获取CSV的第一行,假设是headers$tmpCsvRow = expand("\n", $mTmp->data);$headers = expand(',', $tmpCsvRow[0]);foreach ($headers 作为 $header){if (!empty($header)){//空白标题是蹩脚的,跳过它们//为 $mForm 数组中找到的每个 CSV 标头添加一个新模型//也可以添加自定义的attributeLabel,$header 是实际的header 名称,如'First Name',//所以ImportParseForm 中header 属性的新标签将是'First Name header' 和//它将正确显示在您的 CActiveForm 视图中$mForm[] = new ImportParseForm(array('header' => $header.' header'));}}

$mForm 推送到您的视图.现在,在您看来,像这样为您的表单遍历 $mForm(类似于 wiki 文章,但我在这里使用的是 CActiveForm 小部件):

 $mItem): ?><div class="row"><?php echo $fParse->labelEx($mItem,"[$m]header");?>映射到<?php echo $fParse->textField($mItem, "[$m]header");?><?php echo $fParse->error($mItem, "[$m]header");?>

<?php endforeach;?>

验证按预期工作.

如果要使用 AJAX 验证,请在控制器中使用 CActiveForm::validateTabular()(而不是普通的 validate()).

希望这对其他 Yii 初学者有所帮助!:)

Situation

I used the wiki article on Yii's site, Collecting Tabular Input, to follow as an example.

I don't believe I need to validate tabular input in a traditional sense against multiple models. I only have one model, but I'm dynamically creating the number of fields in the form. Here's a bit more background.

I'm importing CSV files where its headers vary in order among the different files. Before correctly parsing the files, the user needs to map which header would map to what table/column.

I have a single model, ImportParseForm extended from CFormModel. It really only has one rule:

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

Here's a snippet of my view:

<?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; ?>

Here's a snippet of my controller:

        $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
            }
        }

If all fields are valid, then it passes as expected. The problem is if one of the fields are invalid (or in this case, empty), then all fields are flagged as invalid.

In Yii 1.1.10, they added CActiveForm::validateTabular(), but it looks like it's for multiple models. Not quite what I have here. But for kicks, I added the following to my controller (removed the other type of validation, of course):

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

The form itself is only valid if the first element is populated. If the first element is populated, it will set all the other elements with that same value (and passes validation).

Question

Basically, can I use CActiveForm to do validation against fields that are dynamically generated (similar to tabular input, but with only one model)?

解决方案

After reading Collecting Tabular Input a bit closer, I am using "multiple" models. I misunderstood that multiple models would mean multiple different structured models and not just multiple of the same structured model in an array. For example, in the wiki there's a piece that shows what items (array of models) to update: $items=$this->getItemsToUpdate();. My corrected assumption is that that particular method grabs multiple of the same structured model but with different primary keys... or different records. Understanding that, the rest of the article makes more sense ;)

But here's my model solution on how to create a CSV header mapping form.

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);
    }
}

Here is a snippet in my controller on what my equivalent to $items=$this->getItemsToUpdate(); (again, the goal is to collect an array of models) would look like

        // 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'));
            }
        }

Push $mForm to your view. Now in your view, iterate through $mForm for your form like so (similar to the wiki article, but I'm using a CActiveForm widget here):

<?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; ?>

Validation works as expected.

If you want to use AJAX validation, use CActiveForm::validateTabular() in your controller (instead of the normal validate()).

Hope this helps other Yii beginners! :)

这篇关于在 Yii 中,有没有办法使用 CActiveForm 验证表格输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
PHP最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆