Question

Je suis en train de construire une forme de plusieurs pages avec Yû, mais je suis tout à fait nouveau pour PHP et Yû et je me demande quelle est la meilleure pratique pour écrire un formulaire de plusieurs pages. Jusqu'à présent, ce que je prévois de faire est d'ajouter un champ caché nommé « étape » qui contient l'étape actuelle de l'utilisateur est sous la forme (le formulaire est divisé en 3 étapes / pages). Donc, avec cela à l'esprit, voici comment je prévois de gérer le utilisateur en cliquant sur les boutons précédent / suivant dans le contrôleur:

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);
  }
 }

Est-ce que cette approche a du sens? Ou suis-je loin base et il y a une façon beaucoup mieux et plus optimisé de le faire dans Yii / PHP?

Merci!

Était-ce utile?

La solution

Il y a deux façons d'aborder ce sujet. Je vous qu'affiche le forum Yii donc je suppose que vous avez effectué une recherche autour de là-bas aussi, mais dans le cas où vous n'avez pas:

Ce que je l'ai fait est (juste pour un simple formulaire ActiveRecord 2 étapes) pris une seule action et divisé en blocs conditionnels en fonction du nom du bouton qui Yii POSTs sur un formulaire soumettre (note: ne fonctionne pas avec ajax soumet). Ensuite, en fonction du bouton a été frappé, je rends la forme correcte et définissez le scénario correct sur mon modèle à des fins de validation.

Un caché « étape » champ comme vous avez pu servir le même but que la vérification du nom de submitButton. Je voudrais peut-être sauver la « étape » dans l'état de forme au lieu d'ajouter un champ caché bien, mais soit serait bien.

Certaines personnes utilisent l'attribut stateful ActiveForm pour enregistrer les données à partir d'une seule étape de l'assistant, ou vous pouvez utiliser la session, ou même enregistrer sur une table de base de données temporaire. Dans mon exemple complètement non testé ci-dessous, je me sers d'une fonctionnalité de la forme stateful.

Voici un exemple de ce que je faisais essentiellement une forme ActiveRecord. Cela va dans le "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));
} ?>

Les formes ressemblerait à quelque chose comme ceci:

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(); ?>

Formulaire 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(); ?>

J'espère que c'est utile!

Autres conseils

Yû fournit une fonctionnalité appelée états de page pour mettre en œuvre des choses comme un assistant de forme multi-étapes / multipage.

Permet de jeter un oeil à la documentation Yii premier:

  

Un état de page est une variable qui persiste à travers les requêtes POST de la même page. Pour utiliser les états de page persistants, la forme (s) doit être stateful qui sont générés en utilisant {@link CHtml :: statefulForm}.

Ainsi, les formes de tous les besoins étape / page à des formes stateful. Pour rendre un formulaire stateful il vous suffit de définir la propriété CActiveForm::stateful à true lorsque vous démarrez le ActiveForm-widget. Au sein de votre contrôleur, vous pouvez obtenir et définir vos états de page avec CController::getPageState() ou CController::setPageState().

Alors ce sont les bases qui fonctionnent très bien si la mise en œuvre de votre assistant de formulaire multi page est faite dans le style traditionnel, sans les requêtes AJAX.

Si toutefois vous souhaitez utiliser AJAX appelle à soumettre des données étape et afficher l'étape suivante, les états de page de Yii ne sont pas utilisables.

Pourquoi? Tous les états de page sont transportés via HTTP POST dans un champ de saisie caché. Le champ d'entrée est rempli par Yû alors que le soi-disant traitement de sortie. Le traitement de sortie démarre après le rendu et remplacera les pièces de la sortie. Alors états de page La fonction de Yû nécessite le traitement de sortie . réponses AJAX d'autre part peuvent être endommagées par elle parce que le traitement de sortie peut également ajouter des balises ou <link> <script> au début de la sortie à la charge requise JS et les fichiers CSS.

En fin de compte, je mis en œuvre ma propre version de formes stateful. Je suis en mesure d'obtenir mes données stateful avec l'appel de fonction statique ActiveFormWidget::getRequestMultiStepData() chaque fois que je besoin.

Avis: Il y a un inconvénient dans ma mise en œuvre: tous les besoins de données stateful à recueillir avant que le formulaire widget sera initialisé. Mais je ne ai jamais eu un problème avec elle jusqu'à présent. Cependant le code ici:

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;
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top