我在 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/