2

名前と呼ばれるモデルのプロパティにテキストフィールドを動的に追加していますが、ビューの配列名のすべての名前に検証ルールを設定したいのですが、CForm モデルで検証ルールを使用せずにこれを行うことは可能ですか?、たとえばボタンをクリックした後、すべての名前が必要になることを検証したいと思います。

これは、CActiveForm を使用したビューのコードです

<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'test',
'enableClientValidation'=>true,
'clientOptions'=>array(
    'validateOnSubmit'=>true,
),
)); ?>

<p class="note">Campos <span class="required">*</span> son obligatorios.</p>

<div class="row">
    <?php echo $form->labelEx($model,'Age'); ?>
    <?php echo $form->textField($model,'age'); ?>
    <?php echo $form->error($model,'age'); ?>
</div>

<div class="row">
    <?php echo $form->labelEx($model,'Name'); ?>
    <?php echo $form->passwordField($model,'names[0]'); ?>
    <?php echo $form->error($model,'names[0]'); ?>

</div>

<div class="row">
    <?php echo $form->labelEx($model,'Name'); ?>
    <?php echo $form->passwordField($model,'names[1]'); ?>
    <?php echo $form->error($model,'names[1]'); ?>

</div>

<div class="row buttons">
        <?php echo CHtml::submitButton('test'); ?>
    </div>

<?php $this->endWidget(); ?>
4

2 に答える 2

1

検証される属性が配列であると想定し、別のバリデーターの結果をその各要素に適用するカスタムバリデーターを作成する必要があります。

上記を正確に行うこのバリデーターを出発点として使用しました。少しクリーンアップして可能な限り単純化した後、サーバー側の検証用に次のコードに到達しました。

protected function validateAttribute($object, $attribute)
{
    $value = $object->$attribute;

    if (!is_array($value) ) {
        $this->addError($object, $attribute, "TODO: error message");
        return;
    }
    else if ($this->isEmpty($value)) {
        if (!$this->allowEmpty) {
            $this->addError($object, $attribute, "TODO: error message");
        }

        return;
    }

    // $this->validator and $this->parameters are supposed to be
    // attributes of your custom validator class that you set from
    // inside rules().
    $validator = self::createValidator(
        $this->validator,
        $object,
        array($attribute),
        $this->parameters);

    $errors = array();

    // Iterate over $value, validating each item in turn.
    // Since $validator may be a filtering validator, we need to make
    // sure that any changes it makes to the validated item stick, so
    // we iterate by reference and do a bit of back and forth shuffling.
    foreach($value as $key => &$item) {
        $object->$attribute = $item; // the only way
        $validator->validateAttribute($object, $attribute);
        $item = $object->$attribute; // make any changes stick

        if ($object->hasErrors($attribute)) {
            $errors[$key] = $object->gerErrors($attribute);
            $object->clearErrors($attribute);
        }
    }

    unset($item); // always a good idea after foreach by reference
    $object->$attribute = $value; // undo the damage

    // And now decide what to do with $errors, which is per-item.
    // This should be good:
    foreach ($errors as $key => $error) {
         $object->addError("$attribute[$key]", $error);
    }
}

わかりましたが、クライアント側の検証はどうでしょうか? これは可能であるように思われますが、私はそれをテストしていません:

public function clientValidateAttribute($object,$attribute)
{
    // Since this is copy/pasted from above, it's an obvious candidate
    // for refactoring into a private method. I 'm keeping it simple.
    $validator = self::createValidator(
        $this->validator,
        $object,
        array($attribute),
        $this->parameters);

    $js = '';

    // No need for filtering support here (I think...)
    foreach($value as $key => $item) {
        $object->$attribute = $item;
        $js .= $validator->clientValidateAttribute($object, $attribute);
    }

    return $js;        
}
于 2013-03-27T10:15:40.350 に答える
0

まず、モデル内でリレーションを指定する必要があります。

'user' => array(self::BELONGS_TO, 'User', 'user_id'),

次に、検索機能でその関係を次のように使用します。

$criteria->with=array('user');

そして、それを次のようにビューで使用します。

array(
'name'=>'username_search',
'value'=>'$data->user->username',
'header'=>'Posted By',
),
于 2013-03-26T09:25:03.000 に答える