【问题标题】:Validation for parent_id in yii2在 yii2 中验证 parent_id
【发布时间】:2016-08-05 13:25:20
【问题描述】:

您好,我在验证时遇到问题,我正在使用 yii2 Advanced 应用程序。

我在创建菜单时有一个 parent_id,我给菜单名称并提供天气这个菜单是否是父菜单,如果父菜单复选框被选中,如果没有,那么从下拉菜单将被选中。

问题是,如果根据规则在模型中设置此父 ID,则在视图中复选框和下拉菜单都将验证并且两者都将显示为必需的。但我只想要其中任何一个。如果我没有按要求提供,那么验证本身就不会发生。见下图。

这是我的活动表格..

   <?= $form->field($model, 'parent_id')->checkbox(array( 
    'id'=>'new', 
    'value'=>'0',
    'labelOptions'=>array('style'=>'padding:5px;'), 
    'disabled'=>false 
    )); ?>

<div class="select" id="select"> 
<?= $form->field($model,'parent_id')->widget(Select2::classname(), [
'data' => $menu,
'options' => ['placeholder' => 'Select a Menu name ...'],
'pluginOptions' => [
    'allowClear' => true
],
]); ?>
</div>

如果两者都留空,我希望进行验证。请告诉我任何解决方案。

【问题讨论】:

    标签: php forms validation yii2 yii2-advanced-app


    【解决方案1】:

    首先,如果我确实正确理解了您的要求,为了获得更简洁的代码,我建议向您的 model 类引入一个新的虚拟属性,而不是为同一属性分配不同值的 2 个字段:

    $form->field($model,'is_parent')->checkbox(...) // don't do 'value'=>'0' here. it will be auto mapped to model virtual attribute.
    $form->field($model,'parent_id')->widget(...)
    /*
     instead of :
       $form->field($model,'parent_id')->checkbox(...) // parent_id is 1 or 0 here
       $form->field($model,'parent_id')->widget(...)
    */
    

    然后使用when 属性将Conditional Validation 应用到您的模型 规则中:

    public $is_parent;
    
    public function rules()
    {
        return [
            ['is_parent', 'boolean'],
            // 'parent_id' is required only if the checkbox is not checked
            ['parent_id', 'required', 'when' => function($model) {
                return !$model->is_parent;
            }],
        ];
    }
    

    注意:链接的文档还说:

    如果您还需要支持客户端条件验证,您可以 应该配置接受字符串的 whenClient 属性 表示一个 JavaScript 函数,其返回值决定 是否应用规则。

    这是预期的,因为客户端验证脚本基于您的初始规则。所以你有2个选择。要么在 ActiveForm 中完全禁用它,而是使用 Ajax 验证:

    <?php $form = ActiveForm::begin([
        ...
        'enableClientValidation' => false,
        'enableAjaxValidation' => true
    ]); ?>
    

    或者另一种选择是将缺少的客户端相关脚本添加到您的规则中,如文档中所示,在您的情况下可能如下所示:

    public function rules()
    {
        return [
            ['is_parent', 'boolean'],
    
            ['parent_id', 'required', 'when' => function($model) {
                return !$model->is_parent;
            }, 'whenClient' => "function (attribute, value) {
                return !$('#menu-is_parent').val();
            }"],
        ];
    }
    
    • 请注意,我确实希望您的 formName() 返回 'menu'。默认情况下,它返回模型类名称。您还可以使用浏览器的开发工具检查复选框输入,并查看 Yii 分配给它的 id 是什么。

    最后,如果在选中复选框时应设置特定的 parent_id 值,您可以使用 beforeSave()afterValidate() 手动将其设置为您需要的任何值,例如:

    public function beforeSave($insert)
    {
        if ($this->is_parent) $this->parent_id = $someModel->id;
        return parent::beforeSave($insert);
    }
    

    【讨论】:

    • 我尝试了你的建议,但它不起作用,即使我选中了 parent_id 正在验证的复选框并且它是必需的。
    • 检查更新。我猜您已将 enableClientValidation 设置为 true,因为默认情况下就是这种情况。如果是这种情况,您需要改用 ajax 验证或将相关的 WhenClient 代码添加到您的规则中。
    • 那么成功了吗?您是否尝试过我作为注释部分添加到答案中的内容?
    • 那么其他地方应该是错误的,因为我在上次更新之前确实尝试了代码。您是否删除了旧的 'parent_id' 相关规则并只留下条件规则?您是否尝试禁用客户端代码?是否有其他东西迫使$model-&gt;is_parent 持有不同的价值?尝试手动将验证伪造为 $model = new Menu();$model-&gt;load(['menu'=&gt;['parent_id'=&gt;'','is_parent'=&gt;1]]);$model-&gt;validate();print_r($model-&gt;errors); 之类的不同操作,看看它给出了什么。这应该有助于调试应用程序。祝你好运。
    【解决方案2】:

    我认为您必须为此目的使用自定义验证:

    public function rules()
        {
            return [
                ['field1', function ($attribute, $params) {
                        // if (...) 
                        $this->addError($attribute, 'Must field1 or field2 be set');
                    }
                }],
            ];
        }
    

    【讨论】:

      猜你喜欢
      • 2016-09-07
      • 2011-02-21
      • 1970-01-01
      • 1970-01-01
      • 2017-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多