2010-08-23 12 views
23

मैं वाईआई के साथ एक बहु-पृष्ठ फ़ॉर्म बनाने की कोशिश कर रहा हूं, लेकिन PHP और Yii के लिए काफी नया हूं और यह सोच रहा हूं कि बहु पृष्ठ फ़ॉर्म लिखने के लिए सबसे अच्छा अभ्यास क्या है। अब तक, मैं जो करने की योजना बना रहा हूं वह 'चरण' नामक एक छिपे हुए फ़ील्ड को जोड़ना है जिसमें उपयोगकर्ता के रूप में वर्तमान चरण है (फॉर्म 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); 
    } 
} 

करता है इस दृष्टिकोण मतलब? या क्या मैं आधार से दूर हूं और वाईआई/PHP में ऐसा करने का एक बेहतर और अधिक अनुकूलित तरीका है?

धन्यवाद!

+4

'CHTML पर एक नजर डालें :: statefulForm' और एक [Yii मंच पर धागा] (http://www.yiiframework.com/forum/index.php?/topic/ 8413-जादूगर-रूप /) –

उत्तर

35

इस तक पहुंचने के कुछ तरीके हैं। मैं तुम्हें Yii मंच में तैनात देख तो मैं तुम वहाँ के आसपास भी खोज की है मान लेते हैं लेकिन मामले में आप नहीं है:

मैंने क्या किया है (बस एक साधारण 2-चरणीय ActiveRecord फ़ॉर्म के लिए) एक ही कार्रवाई की और इसे बटन नाम के आधार पर सशर्त ब्लॉक में विभाजित किया गया, जो एक फॉर्म पर Yii POSTs सबमिट करता है (नोट: AJAX सबमिट के साथ काम नहीं करता है)। फिर, किस बटन पर हिट किया गया था, इस पर निर्भर करता हूं कि मैं सही फॉर्म प्रस्तुत करता हूं और सत्यापन उद्देश्यों के लिए अपने मॉडल पर सही परिदृश्य सेट करता हूं।

आपके जैसे छुपा "चरण" फ़ील्ड सबमिट बटन की जांच के समान उद्देश्य प्रदान कर सकता है। हालांकि मैं शायद एक छिपे हुए क्षेत्र को जोड़ने के बजाय "चरण" को फॉर्म स्थिति में सहेज दूंगा, लेकिन यह ठीक होगा।

कुछ लोग विज़ार्ड में एक ही चरण से डेटा को सहेजने के लिए राज्य सक्रिय सक्रिय फर्म विशेषता का उपयोग करते हैं, या आप सत्र का उपयोग कर सकते हैं, या यहां तक ​​कि एक temp डेटाबेस तालिका में भी सहेज सकते हैं। नीचे मेरे पूरी तरह से अवांछित उदाहरण में मैं एक स्टेटफुलर फॉर्म कार्यक्षमता का उपयोग कर रहा हूं।

यहां एक उदाहरण है जो मैंने मूल रूप से ActiveRecord फ़ॉर्म के लिए किया था।

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

फार्म 2:

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

रूपों कुछ इस तरह दिखेगा: यह "actionCreate" में चला जाता है

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

मुझे आशा है कि है उपयोगी!

+1

धन्यवाद कि बहुत उपयोगी था! मुझे प्रदर्शित करने के लिए कौन सा चरण निर्धारित करने के लिए सबमिट बटन का उपयोग करने के अपने दृष्टिकोण को पसंद है। मैं ActiveForm दृष्टिकोण को भी देखूंगा, जो दिलचस्प लगता है। –

+0

धन्यवाद आवंटित। मैं इस तरह और सामान कहां से सीख सकता हूं? वाईआई ढांचे के साथ पेशेवर विकास की तरह। – FDisk

+1

"नोट: AJAX सबमिट के साथ काम नहीं करता" के बारे में, यह सच है, विशेष रूप से jquery में, लेकिन आप form.serialize के परिणाम में बटन नाम/मान जोड़ सकते हैं और –

4

वाईआई एक बहु चरण/बहु पृष्ठ फॉर्म विज़ार्ड जैसी चीजों को लागू करने के लिए पृष्ठ राज्य नामक एक सुविधा प्रदान करता है।

एक पेज राज्य एक चर है कि एक ही पेज के पोस्ट अनुरोध के दौरान जारी रहता है:

Yii डॉक्स पहले पर एक नजर है की सुविधा देता है। लगातार पृष्ठ राज्यों का उपयोग करने के लिए, फ़ॉर्म (ओं) को राज्यव्यापी होना चाहिए जो {@link CHtml :: statefulForm} का उपयोग करके उत्पन्न होता है।

तो प्रत्येक चरण/पृष्ठ के रूपों को राज्य के रूपों की आवश्यकता है।एक स्टेटफुल फॉर्म को प्रस्तुत करने के लिए आपको CActiveForm::stateful प्रॉपर्टी को true पर सेट करने की आवश्यकता है जब आप ActiveForm-widget प्रारंभ करते हैं। अपने नियंत्रक के भीतर आप CController::getPageState() या CController::setPageState() के साथ अपने पृष्ठ के राज्यों को प्राप्त और सेट कर सकते हैं।

तो ये मूल बातें हैं जो आपके बहु पृष्ठ फॉर्म विज़ार्ड के कार्यान्वयन को बिना किसी AJAX अनुरोधों के पारंपरिक शैली में बनाया गया है।

यदि आप चरण डेटा जमा करने और अगले चरण को प्रदर्शित करने के लिए AJAX कॉल का उपयोग करना चाहते हैं, तो वाईआई के पृष्ठ राज्य उपयोग योग्य नहीं हैं।

क्यों? सभी पृष्ठ राज्यों को एक छिपे इनपुट क्षेत्र के भीतर HTTP-POST के माध्यम से पहुंचाया जाता है। इनपुट फ़ील्ड वाईआई द्वारा भर जाता है जबकि तथाकथित आउटपुट प्रोसेसिंग। उत्पादन प्रक्रिया प्रतिपादन के बाद शुरू होती है और आउटपुट के हिस्सों को प्रतिस्थापित करेगी। तो वाईआई के पेज स्टेटस फीचर आउटपुट प्रोसेसिंग की आवश्यकता है। दूसरी ओर AJAX प्रतिक्रियाएं इसके द्वारा दूषित हो सकती हैं क्योंकि आउटपुट प्रोसेसिंग आवश्यक जेएस और सीएसएस फ़ाइलों को लोड करने के लिए आउटपुट की शुरुआत में <link> या <script> टैग भी जोड़ सकता है।

अंत में मैंने राज्य के रूपों का अपना संस्करण लागू किया। मैं हर बार जब मुझे इसकी आवश्यकता होती है तो स्थिर स्टेट कॉल 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; 
     } 
    } 
} 
संबंधित मुद्दे