Model view controller Yii2验证多个模型

Model view controller Yii2验证多个模型,model-view-controller,yii2,yii2-model,Model View Controller,Yii2,Yii2 Model,我在Yii2中有两个模型(masterTransaction和splitTransaction),其中每个masterTransaction可以有多个splitTransaction。每个splitTransaction都有一个属性“amount”。我的问题是我需要验证所有“金额”属性的总和是否为0 我的第一个解决方案是创建另一个名为Transaction的模型,在该模型中,我有一个属性,其中保存了masterTransaction模型的一个实例,另一个属性保存了一组splitTransacti

我在Yii2中有两个模型(masterTransaction和splitTransaction),其中每个masterTransaction可以有多个splitTransaction。每个splitTransaction都有一个属性“amount”。我的问题是我需要验证所有“金额”属性的总和是否为0

我的第一个解决方案是创建另一个名为Transaction的模型,在该模型中,我有一个属性,其中保存了masterTransaction模型的一个实例,另一个属性保存了一组splitTransaction实例。我用一个定制的内联validatior进行了验证,它工作得非常好

交易模型 用于创建模型的控制器函数
公共函数actionCreate()
{
$transaction=新事务();
$count=count(Yii::$app->request->post('SplitTransaction',[]);
对于($i=1;$i<$count;$i++){
$transaction->splitTransactions[]=新建SplitTransaction();
}
如果($transaction->masterTransaction->load(Yii::$app->request->post())和&Model::loadMultiple($transaction->splitTransactions,Yii::$app->request->post()){
$transaction->masterTransaction->user_id=Yii::$app->user->id;
foreach($transaction->splitTransactions作为$splitTransaction){
$splitTransaction->user_id=Yii::$app->user->id;
}
如果($transaction->validate()){
$transaction->save();
}
}
返回$this->render('create'[
“事务”=>$transaction,
]);
}
但是当我试图构建一个表单来输入数据时,我遇到了Ajax验证的问题。验证会起作用,但是我不知道把错误信息放在哪里,所以它只是删除了它

我怀疑这不是Yii2模型中我的数据的首选方式,但我真的没有其他想法。也许有人对我有一些想法。

选项1。 这取决于您的视图文件代码。您的表单是否包含“splitTransactions”变量?如果不是,你可以这样说

<?= $form->field($model, 'splitTransactions')->hiddenInput(['maxlength' => true])->label(false); ?>
选项2。 您可以像这样向其他变量(表单包含)添加错误

$model->splitTransactions=1;
public function validateSplitTransactions($attribute, $params)
{
    $sum = 0;
    foreach ($this->$attribute as $transaction) {
        $sum = bcadd($sum, $transaction->amount, 3);
    }
    if ($sum != 0) {
        $this->addError('transaction_number', 'The sum of the entries has to be 0');
    }
}
看,表单应该包含“transaction_number”变量。错误将添加到“交易编号”输入中


选项3。以我的经验。 最好将ajax验证与表单操作url分离。例如,为ajax验证创建另一个控制器操作并使用它

范例

创建模型反馈形式

class FeedbackForm extends Model
{
    public $name;
    public $email;
    public $text;


    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['name', 'email', 'text'], 'required'],
            [['name', 'email'], 'string', 'max' => 128],
            [['email'], 'email'],
            [['text'], 'string', 'max' => 512],
        ];
    }

    public function attributeLabels()
    {
        return [
            'name' => \Yii::t('front', 'Name'),
            'email' => \Yii::t('front', 'Email'),
            'text' => \Yii::t('front', 'Message text'),
        ];
    }
}
将操作放到SiteSontroller

public function actionFeedback()
{
    $model=  new \frontend\models\FeedbackForm;
    $model->load(Yii::$app->request->post());
    if($model->validate()) {
        $newFeed=new  \frontend\models\Feedback;
        $newFeed->create_time=new \yii\db\Expression('NOW()');
        $newFeed->name=$model->name;
        $newFeed->email=$model->email;
        $newFeed->is_new=1;
        $newFeed->text=$model->text;
        if($newFeed->save()) {
            \Yii::$app->session->setFlash('success', \Yii::t('front', 'Your message has accepted'));
        } else {
            \Yii::$app->session->setFlash('error', \Yii::t('front', 'Error on save'));
        }
    } else {
        \Yii::$app->session->setFlash('error', \Yii::t('front', 'Data error'));
    }
    return $this->redirect(['/site/index']);
}


public function actionFeedbackvalidate()
{   
     Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

    $model=  new \frontend\models\FeedbackForm;

    $model->load(Yii::$app->request->post());


    return ActiveForm::validate($model);
}
并创建表单内部视图

                <?php $model=new \frontend\models\FeedbackForm; ?>
                <?php $form = ActiveForm::begin([
                        'enableClientValidation' => true,
                        'enableAjaxValidation' => true,
                        'validationUrl'=>['/site/feedbackvalidate'],
                        'validateOnSubmit' => true,
                        'id' => 'form-feedback',
                        'action'=>['/site/feedback'],
                        'options'=>['class'=>'some class', 'autocomplete'=>'off']
                    ]); ?>
                        <?= $form->field($model, 'name')->textInput(['maxlength' => true, 'placeholder'=>$model->getAttributeLabel('name'), 'autocomplete'=>'off'])->label(false); ?>
                        <?= $form->field($model, 'email')->textInput(['maxlength' => true, 'placeholder'=>$model->getAttributeLabel('email'), 'autocomplete'=>'off'])->label(false); ?>
                        <?= $form->field($model, 'text')->textarea(['maxlength' => true, 'placeholder'=>$model->getAttributeLabel('text'), 'autocomplete'=>'off'])->label(false); ?>


                    <div class="form-group">
                        <input type="submit" class="btn btn-default" value="<?php echo Yii::t('front', 'Send') ?>">
                    </div>
                <?php ActiveForm::end(); ?>


您好,朋友们,请添加代码为什么要在另一个模型中创建多个模型?为什么不将它们合并到一个模型中,如果它通过了验证,那么就保存它。您不应该在控制器内部进行任何检查
public function actionFeedback()
{
    $model=  new \frontend\models\FeedbackForm;
    $model->load(Yii::$app->request->post());
    if($model->validate()) {
        $newFeed=new  \frontend\models\Feedback;
        $newFeed->create_time=new \yii\db\Expression('NOW()');
        $newFeed->name=$model->name;
        $newFeed->email=$model->email;
        $newFeed->is_new=1;
        $newFeed->text=$model->text;
        if($newFeed->save()) {
            \Yii::$app->session->setFlash('success', \Yii::t('front', 'Your message has accepted'));
        } else {
            \Yii::$app->session->setFlash('error', \Yii::t('front', 'Error on save'));
        }
    } else {
        \Yii::$app->session->setFlash('error', \Yii::t('front', 'Data error'));
    }
    return $this->redirect(['/site/index']);
}


public function actionFeedbackvalidate()
{   
     Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

    $model=  new \frontend\models\FeedbackForm;

    $model->load(Yii::$app->request->post());


    return ActiveForm::validate($model);
}
                <?php $model=new \frontend\models\FeedbackForm; ?>
                <?php $form = ActiveForm::begin([
                        'enableClientValidation' => true,
                        'enableAjaxValidation' => true,
                        'validationUrl'=>['/site/feedbackvalidate'],
                        'validateOnSubmit' => true,
                        'id' => 'form-feedback',
                        'action'=>['/site/feedback'],
                        'options'=>['class'=>'some class', 'autocomplete'=>'off']
                    ]); ?>
                        <?= $form->field($model, 'name')->textInput(['maxlength' => true, 'placeholder'=>$model->getAttributeLabel('name'), 'autocomplete'=>'off'])->label(false); ?>
                        <?= $form->field($model, 'email')->textInput(['maxlength' => true, 'placeholder'=>$model->getAttributeLabel('email'), 'autocomplete'=>'off'])->label(false); ?>
                        <?= $form->field($model, 'text')->textarea(['maxlength' => true, 'placeholder'=>$model->getAttributeLabel('text'), 'autocomplete'=>'off'])->label(false); ?>


                    <div class="form-group">
                        <input type="submit" class="btn btn-default" value="<?php echo Yii::t('front', 'Send') ?>">
                    </div>
                <?php ActiveForm::end(); ?>