model-view-controller - Yii2 验证多个模型

标签 model-view-controller yii2 yii2-model

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

我的第一个解决方案是创建另一个名为 Transaction 的模型,其中我有一个属性,我在其中保存了 masterTransaction 模型的一个实例,以及另一个带有 splitTransaction 实例数组的属性。我使用自定义内联验证器进行了验证,效果很好。

交易模式

class Transaction extends Model
{
    public $masterTransaction;
    public $splitTransactions;

    public function init()
    {
        $this->masterTransaction = new MasterTransaction();
        $this->splitTransactions[] = new SplitTransaction();
    }

    public function rules()
    {
        return [
            ['splitTransactions', 'validateSplitTransactions'],
        ];
    }

    public function validateSplitTransactions($attribute, $params)
    {
        $sum = 0;
        foreach ($this->$attribute as $transaction) {
            $sum = bcadd($sum, $transaction->amount, 3);
        }
        if ($sum != 0) {
            $this->addError($attribute, 'The sum of the entries has to be 0');
        }
    }

    public function save()
    {
        $this->masterTransaction->save();
        foreach ($this->splitTransactions as $splitTransaction) {
            $splitTransaction->master_transaction_id = $this->masterTransaction->id;
            $splitTransaction->save();
        }
    }
}

用于创建模型的 Controller 函数
public function actionCreate()
{
    $transaction = new Transaction();
    $count = count(Yii::$app->request->post('SplitTransaction', []));
    for ($i = 1; $i < $count; $i++) {
        $transaction->splitTransactions[] = new SplitTransaction();
    }

    if ($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 as $splitTransaction) {
            $splitTransaction->user_id = Yii::$app->user->id;
        }
        if ($transaction->validate()) {
            $transaction->save();
        }
    }

    return $this->render('create', [
        'transaction' => $transaction,
    ]);
}

但是当我尝试构建一个表单来输入数据时,我遇到了 Ajax 验证的问题。验证会起作用,但 Yii 不知道将错误消息放在哪里,所以它只是将其删除。

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

最佳答案

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

<?= $form->field($model, 'splitTransactions')->hiddenInput(['maxlength' => true])->label(false); ?>

该变量将被隐藏,但仍会显示错误。在某些情况下,由于“splitTransactions”变量为空值,不会触发验证。
“splitTransactions”应该包含一些值来触发验证。在像这样粘贴表单之前,您可以为 if 设置一些值
$model->splitTransactions=1;

选项 2。
您可以像这样向其他变量(表单包含)添加错误
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”变量。错误将被添加到“transaction_number”输入中。

选项 3。根据我的经验 .
最好将 ajax 验证与表单操作 url a.g. 分开。为 ajax 验证创建另一个 Controller 操作并使用它。

例子

创建模型反馈表
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);
}

并在 View 中创建表单
                <?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(); ?>

这就对了

关于model-view-controller - Yii2 验证多个模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35529206/

相关文章:

mysql - 如何删除yii2 Controller 中两个表中的数据

c# - MVC 5 Razor Url.Content(空)

Java Observer/Observable 模式不通知

asp.net-mvc - mvc中重定向授权失败

php - 如何在不创建模型的情况下使用标准 Yii2 验证器验证 PHP 中的变量?

javascript - Yii2:比较表格/数组输入中的开始和结束时间

sql - 如何将后端数据(变量)显示到前端页面

yii2 - 如何在 yii2 的目录中创建目录并将文件上传到该目录

c# - ASP.Net Mvc - View 调用可能导致数据检索的函数是否可以接受?

activerecord - yii2 按关系列获取事件记录