Intereting Posts
Есть ли необходимость использовать амперсанд перед объектом? переменные, передающие ничего, показывают неопределенную ошибку переменной, поэтому вы хотите поместить значение по умолчанию для переменной Сортировка массива и сохранение значений ключей PHP CURL ничего не возвращает Как изменить загруженное изменение пути по умолчанию на CKFinder с помощью php PDO rowCount и fetchColumn, которые не возвращают правильный результат Построение черты Singleton с PHP 5.4 проверить пользователя по электронной почте на PHP php отправляет электронную почту через gmail (php.ini) с внутренней почтовой функцией php (win7) JWT API с Laravel, не может читать заголовок обновления токена на клиенте перезаписать функцию поиска в wordpress (sql и php) Регулярное выражение для шаблонов слишком сильно захватывает Что такое JSP-эквивалент json_encode (в PHP)? Фильтровать, сортировать и разбивать на страницы в Codeigniter Поиск наивысшего ключа / индекса в массиве

Yii многостраничный мастер форм

Я пытаюсь создать многостраничную форму с Yii, но я совершенно новичок в PHP и Yii, и мне интересно, что лучше всего подходит для написания многостраничной формы. Пока что я планирую добавить скрытое поле с именем «step», которое содержит текущий шаг, который пользователь включен в форму (форма разбита на 3 шага / страницы). Поэтому, имея в виду это, я планирую обращаться с пользователем, нажимая на предыдущие / следующие кнопки в контроллере:

public function actionCreate() { $userModel = new User; $data['activityModel'] = $activityModel; $data['userModel'] = $userModel; if (!empty($_POST['step'])) { switch $_POST['step']: case '1': $this->render('create_step1', $data); break; case '2': $this->render('create_step2', $data); break; }else { $this->render('create_step1', $data); } } 

Имеет ли смысл этот подход? Или я далеко от базы, и есть намного лучший и более оптимизированный способ сделать это в Yii / PHP?

Благодаря!

Есть несколько способов приблизиться к этому. Я вижу, что вы размещены на форуме Yii, поэтому я предполагаю, что вы обыскали там тоже, но если у вас нет:

То, что я сделал (просто для простой двухэтапной формы ActiveRecord), предприняло одно действие и разделило его на условные блоки на основе имени кнопки, которые Yii POSTs на форме submit (примечание: не работает с ajax отправляет ). Затем, в зависимости от того, какая кнопка была удалена, я делаю правильную форму и задаю правильный сценарий моей модели для целей проверки.

Скрытое поле «шаг», как и вы, может служить той же цели, что и проверка имени submitButton. Я бы, возможно, сохранил «шаг» в состоянии формы вместо добавления скрытого поля, хотя и все было бы хорошо.

Некоторые люди используют атрибут activeForm для сохранения данных с одного шага в мастере, или вы можете использовать сеанс или даже сохранять таблицу базы данных temp. В моем полностью непроверенном примере ниже я использую функциональность формы с сохранением состояния.

Вот пример того, что я в основном сделал для формы ActiveRecord. Это происходит в «actionCreate»:

 <?php if (isset($_POST['cancel'])) { $this->redirect(array('home')); } elseif (isset($_POST['step2'])) { $this->setPageState('step1',$_POST['Model']); // save step1 into form state $model=new Model('step1'); $model->attributes = $_POST['Model']; if($model->validate()) $this->render('form2',array('model'=>$model)); else { $this->render('form1',array('model'=>$model)); } } elseif (isset($_POST['finish'])) { $model=new Model('finish'); $model->attributes = $this->getPageState('step1',array()); //get the info from step 1 $model->attributes = $_POST['Model']; // then the info from step2 if ($model->save()) $this->redirect(array('home')); else { $this->render('form2',array('model'=>$model)); } else { // this is the default, first time (step1) $model=new Model('new'); $this->render('form1',array('model'=>$model)); } ?> 

Формы выглядели бы примерно так:

Form1:

 <?php $form=$this->beginWidget('CActiveForm', array( 'enableAjaxValidation'=>false, 'id'=>'model-form', 'stateful'=>true, )); <!-- form1 fields go here --> echo CHtml::submitButton("Cancel",array('name'=>'cancel'); echo CHtml::submitButton("On to Step 2 >",array('name'=>'step2'); $this->endWidget(); ?> с <?php $form=$this->beginWidget('CActiveForm', array( 'enableAjaxValidation'=>false, 'id'=>'model-form', 'stateful'=>true, )); <!-- form1 fields go here --> echo CHtml::submitButton("Cancel",array('name'=>'cancel'); echo CHtml::submitButton("On to Step 2 >",array('name'=>'step2'); $this->endWidget(); ?> 

Форма 2:

 <?php $form=$this->beginWidget('CActiveForm', array( 'enableAjaxValidation'=>false, 'id'=>'model-form', 'stateful'=>true, )); <!-- form2 fields go here --> echo CHtml::submitButton("Back to Step 1",array('name'=>'step1'); echo CHtml::submitButton("Finish",array('name'=>'finish'); $this->endWidget(); ?> с <?php $form=$this->beginWidget('CActiveForm', array( 'enableAjaxValidation'=>false, 'id'=>'model-form', 'stateful'=>true, )); <!-- form2 fields go here --> echo CHtml::submitButton("Back to Step 1",array('name'=>'step1'); echo CHtml::submitButton("Finish",array('name'=>'finish'); $this->endWidget(); ?> 

Надеюсь, это полезно!

Yii предоставляет функцию, называемую состояниями страниц, для реализации таких вещей, как мастер создания нескольких шагов / нескольких страниц.

Давайте сначала посмотрим на документы Yii:

Состояние страницы – это переменная, которая является постоянной для запросов POST на той же странице. Чтобы использовать постоянные состояния страниц, форма (формы) должна быть с сохранением состояния, которые генерируются с помощью {@link CHtml :: statefulForm}.

Таким образом, формы каждого шага / страницы должны быть формами с сохранением состояния. Чтобы отобразить форму с сохранением состояния, вам просто нужно установить для CActiveForm::stateful значение true при запуске виджета ActiveForm. Внутри вашего контроллера вы можете получить и установить свои состояния страниц с помощью CController::getPageState() или CController::setPageState() .

Таким образом, это основа, которая работает достаточно хорошо, если реализация вашего мастера создания нескольких страниц выполняется в традиционном стиле без запросов AJAX.

Если, однако, вы хотите использовать вызовы AJAX для отправки данных шага и отображения следующего шага, состояния страниц Yii непригодны для использования.

Зачем? Все состояния страниц переносятся через HTTP-POST в скрытом поле ввода. Поле ввода заполняется Yii при так называемой выходной обработке. Обработка результатов начинается после рендеринга и будет заменять часть вывода. Поэтому функция состояния страниц Yii требует обработки вывода . Ответы AJAX, с другой стороны, могут быть повреждены им, потому что обработка вывода может также добавить теги <link> или <script> в начале вывода для загрузки необходимых файлов JS и CSS.

В итоге я реализовал свою собственную версию форм с сохранением состояния. Я могу получить свои данные с состоянием со статическим вызовом функции ActiveFormWidget::getRequestMultiStepData() каждый раз, когда мне это нужно.

Примечание. В моей реализации есть один недостаток: все данные состояния должны быть собраны до того, как виджет формы будет инициализирован. Но до сих пор у меня не было проблем с этим. Однако вот код:

 class ActiveFormWidget extends CActiveForm { public static $inputNameMultiStepData = '_multiStepData'; public $multiStep = false; public $multiStepData = array(); public function init() { parent::init(); # Hidden-Fields if ($this->multiStep) { echo Html::hiddenField(static::$inputNameMultiStepData, static::encodeInputData($this->multiStepData)); } } /** * Gets all multi step data sent. * @return array|mixed */ public static function getRequestMultiStepData() { return isset($_REQUEST[static::$inputNameMultiStepData]) ? static::decodeInputData($_REQUEST[static::$inputNameMultiStepData]) : array(); } /** * Encodes form data like Yii does for stateful forms. * @param $data * @return string */ public static function encodeInputData($data) { $data = Yii::app()->getSecurityManager()->hashData(serialize($data)); return base64_encode($data); } /** * Decodes form data like Yii does for stateful forms. * @param $data * @return bool|mixed */ public static function decodeInputData($data) { $data = base64_decode($data); $data = Yii::app()->getSecurityManager()->validateData($data); if ($data !== false) { return unserialize($data); } else { return false; } } }