Добрый вечер.
На главной странице сайта расположены несколько форм. Все они используют одну модель, но набор данных в каждой форме свой.
Каждая отдельная форма использует свой сценарий валидации, поэтому для каждой формы создана отдельная модель, которая наследуется от основной модели. Обрабатываются формы в одном контроллере, для каждой формы отдельное действие.
Сейчас это реализовано так(покажу на примере одной из четырёх форм):
Модельclass CallbackForm extends Proposal
{
const SCENARIO_CALLBACK_FORM = 'CallbackForm';
public function rules()
{
return ArrayHelper::merge(parent::rules(), [
[['name', 'phone'], 'required', 'on' => self::SCENARIO_CALLBACK_FORM],
[
'name', 'match', 'pattern' => '#^[а-яё ]+$#iu',
'message' => '«{attribute}» может содержать А-ЯЁ', 'on' => self::SCENARIO_CALLBACK_FORM
],
[
'phone', 'match', 'pattern' => '#\+7 \(\d{3}\) \d{3}-\d{2}-\d{2}#',
'message' => '«{attribute}» должен быть в формате +7(222) 333-44-55', 'on' => self::SCENARIO_CALLBACK_FORM
]
]);
}
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_CALLBACK_FORM] = ['name', 'phone'];
return $scenarios;
}
}
Действие в контролереpublic function actionCallback()
{
$model = new CallbackForm();
$model->scenario = CallbackForm::SCENARIO_CALLBACK_FORM;
if(Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())){
if($model->save()){
$model->sendNoteEmails($model);
$answer = ['success' => true, 'title' => 'Ваша заявка принята.', 'message' => 'SUCCESS'];
}
else{
$message = '';
foreach($model->getErrors() as $value){
$message .= $value[0].'<br>';
}
$answer = ['validation' => true, 'title' => 'Произошла ошибка.', 'message' => $message];
}
return $this->asJson($answer);
}
}
Действие для ajax валидацииpublic function actionAjaxValidate()
{
if(Yii::$app->request->isAjax){
$model = new CallbackForm();
$model->scenario = CallbackForm::SCENARIO_CALLBACK_FORM;
if($model->load(Yii::$app->request->post())){
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
}
}
Форма<?php
$form = ActiveForm::begin([
'id' => 'Callback',
'action' => ['/proposal/default/callback'],
'validationUrl' => Url::toRoute(['/proposal/default/ajax-validate']),
'enableAjaxValidation' => true,
]);
?>
<?= $form->field($callback, 'name')->textInput(['class' => 'b-calcInput', 'placeholder' => 'Иван Иванов'])->label(false) ?>
<?= $form->field($callback, 'phone')->textInput(['class' => 'b-calcInput j-maskTel', 'placeholder' => '+7 (000) 000 00 00'])->label(false) ?>
<?= Html::submitButton('Перезвоните мне', ['class' => 'b-btn b-calcBtn',]) ?>
<?php
ActiveForm::end();
?>
JS для ajax запросаspoiler$('form').on('beforeSubmit', function(e){
console.log('beforeSubmit')
var form = $(this)
console.log(form.serialize())
$.ajax({
type: form.attr('method'),
url: form.attr('action'),
data: form.serialize()
}).done(function(data){
if(data.success){
console.log(data)
ajaxAnswer(data)
}
else if(data.validation){
console.log('validate')
ajaxAnswer(data)
}
else{
}
}).fail(function(){
console.log('fail')
})
return false;
})
Для меня представляет сложность решить проблему, как обработать ajax валидацию для других форм? Сейчас в
actionAjaxValidate можно обработать только одну форму. Как можно изменить действие, чтобы в нём обрабатывались другие формы, то есть, использовать другие модели и другие сценарии?
Пробовал ajax валидацию писать в действии для определённой формы, но тогда у меня получалась двойная отправка формы и запись шла в базу два раза.
Выглядело это такpublic function actionCallback()
{
$model = new CallbackForm();
$model->scenario = CallbackForm::SCENARIO_CALLBACK_FORM;
if(Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())){
if($model->save()){
$model->sendNoteEmails($model);
$answer = ['type' => 'success', 'title' => 'Ваша заявка принята.', 'message' => 'SUCCESS'];
return json_encode($answer);
}
else{
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
}
}
Была мысль для каждой формы сделать отдельный контролер, но это, как я думаю, полнейший бред.
В общем, как обрабатывать все формы в одном действии
actionAjaxValidate?