You must be logged in to view profiles.

Wizard Component 1.2

By jaredhoyt (jaredhoyt)
Automates several aspects of multi-page forms including data persistence, form preparation, wizard resetting (manual and automatic), user navigation, and plot-branching navigation while maintaining flexibility with custom validation and completion callbacks.

Tutorial can be found here: http://bakery.cakephp.org/articles/view/wizard-component-1-2-tutorial
[03/07/08] Update 1.2.3: Fixed bug pertaining to Previous and Cancel buttons not auto-working with submit buttons with type="image".

[11/23/08] Update 1.2.2: Added "lockdown" feature. If $lockdown = true (default false), user will not be able to edit previously completed steps. This is useful for wizards such as tests and surveys in which the user shouldn't be able to edit previous steps.

[11/21/08] Update 1.2.1: Changed visibility of all callbacks to protected (all callbacks must now be preceded with an _). Added auto-validate feature: if $autoValidate = true, then data is automatically validated with the correct model (must be included in controller's uses array) unless a processCallback() is present.

Component Class:

Download code <?php 
/**
 * Wizard component by jaredhoyt.
 *
 * Handles multi-step form navigation, data persistence, validation callbacks, and plot-branching navigation.
 *
 * PHP versions 4 and 5
 *
 * Comments and bug reports welcome at jaredhoyt AT gmail DOT com
 *
 * Licensed under The MIT License
 *
 * @writtenby        jaredhoyt
 * @lastmodified    Date: March 7, 2009
 * @license        http://www.opensource.org/licenses/mit-license.php The MIT License
 */ 
class WizardComponent extends Object {
/**
 * The Component will redirect to the "expected step" after a step has been successfully
 * completed if autoAdvance is true. If false, the Component will redirect to 
 * the next step in the $steps array. (This is helpful for returning a user to 
 * the expected step after editing a previous step w/o them having to navigate through
 * each step in between.)
 *
 * @var boolean
 * @access public
 */
    
var $autoAdvance true;
/**
 * Option to automatically reset if the wizard does not follow "normal"
 * operation. (ie. manual url changing, navigation away and returning, etc.)
 * Set this to false if you want the Wizard to return to the "expected step"
 * after invalid navigation.
 *
 * @var boolean
 * @access public
 */
    
var $autoReset false;
/**
 * If no processCallback() exists for the current step, the component will automatically
 * validate the model data against the models included in the controller's uses array.
 *
 * @var boolean
 * @access public
 */
    
var $autoValidate false;
/**
 * List of steps, in order, that are to be included in the wizard.
 *        basic example: $steps = array('contact', 'payment', 'confirm');
 * 
 * The $steps array can also contain nested steps arrays of the same format but must be wrapped by a branch group.
 *         plot-branched example: $steps = array('job_application', array('degree' => array('college', 'degree_type'), 'nodegree' => 'experience'), 'confirm');
 *
 * The 'branchnames' (ie 'degree', 'nodegree') are arbitrary but used as selectors for the branch() and unbranch() methods. Branches
 * can point to either another steps array or a single step. The first branch in a group that hasn't been skipped (see branch())
 * is included by default (if $defaultBranch = true). 
 *
 * @var array
 * @access public
 */
    
var $steps = array();
/**
 * Controller action that processes your step. 
 *
 * @var string
 * @access public
 */
    
var $wizardAction 'wizard';
/**
 * Url to be redirected to after the wizard has been completed.
 * Controller::afterComplete() is called directly before redirection.
 *
 * @var string
 * @access public
 */
    
var $completeUrl '/';
/**
 * Url to be redirected to after 'Cancel' submit button has been pressed by user.
 *
 * @var string
 * @access public
 */
    
var $cancelUrl '/';
/**
 * If true, the first "non-skipped" branch in a group will be used if a branch has
 * not been included specifically.
 *
 * @var boolean
 * @access public
 */
    
var $defaultBranch true;
/**
 * If true, the user will not be allowed to edit previously completed steps. They will be
 * "locked down" to the current step.
 *
 * @var boolean
 * @access public
 */    
    
var $lockdown false;
/**
 * Internal step tracking.
 *
 * @var string
 * @access protected
 */
    
var $_currentStep null;
/**
 * Holds the session key for data storage.
 *
 * @var string
 * @access protected
 */
    
var $_sessionKey null;
/**
 * Other session keys used.
 *
 * @var string
 * @access protected
 */
    
var $_configKey null;
    var 
$_branchKey null;
/**
 * Other components used.
 *
 * @var array
 * @access public
 */
    
var $components = array('Session');
/**
 * Initializes WizardComponent for use in the controller
 *
 * @param object $controller A reference to the instantiating controller object
 * @access public
 */
    
function initialize(&$controller) {
        
$this->controller =& $controller;
        
        
$this->_sessionKey    $this->Session->check('Wizard.complete') ? 'Wizard.complete' 'Wizard.' $controller->name;
        
$this->_configKey     'Wizard.config';
        
$this->_branchKey    'Wizard.branches.' $controller->name;    
    }
/**
 * Component startup method.
 *
 * @param object $controller A reference to the instantiating controller object
 * @access public
 */    
    
function startup(&$controller) {
        if (!empty(
$this->wizardAction)) {
            
$this->wizardAction .= '/';
        }
        
        
$this->steps $this->_parseSteps($this->steps);
        
        
$this->config('wizardAction'$this->wizardAction);
        
$this->config('steps'$this->steps);
    }
/**
 * Main Component method.
 *
 * @param string $step Name of step associated in $this->steps to be processed.
 * @access public
 */        
    
function process($step) {
        if (isset(
$this->controller->params['form']['Cancel'])) {
            if (
method_exists($this->controller'_beforeCancel')) {
                
$this->controller->_beforeCancel($this->_getExpectedStep());
            }
            
$this->resetWizard();
            
$this->controller->redirect($this->cancelUrl);
        }
        
        if (empty(
$step)) {
            if (
$this->Session->check('Wizard.complete')) { 
                if (
method_exists($this->controller'_afterComplete')) {
                    
$this->controller->_afterComplete();
                }
                
$this->resetWizard();
                
$this->controller->redirect($this->completeUrl);
            }
            
            
$this->autoReset false;
        } elseif (
$step == 'reset') {
            if (!
$this->lockdown) {
                
$this->resetWizard();
            }
        } else {
            if (
$this->_validStep($step)) {
                
$this->_setCurrentStep($step);
                                                
                if (!empty(
$this->controller->data) && !isset($this->controller->params['form']['Previous'])) { 
                    
$proceed false;
                    
                    
$processCallback '_' Inflector::variable('process_' $this->_currentStep);
                    if (
method_exists($this->controller$processCallback)) {
                        
$proceed $this->controller->$processCallback();
                    } elseif (
$this->autoValidate) {
                        
$proceed $this->_validateData();
                    } else {
                        
trigger_error(__('Process Callback not found. Please create Controller::' $processCallbacktrue), E_USER_WARNING);
                    }
                    
                    if (
$proceed) {
                        
$this->save();
                    
                        if (
next($this->steps)) {
                            if (
$this->autoAdvance) {
                                
$this->redirect();
                            }
                            
$this->redirect(current($this->steps));
                        } else {
                            
$this->Session->write('Wizard.complete'$this->read());        
                            
$this->resetWizard();
                            
                            
$this->controller->redirect($this->wizardAction);
                        }
                    }
                } elseif (isset(
$this->controller->params['form']['Previous']) && prev($this->steps)) { 
                    
$this->redirect(current($this->steps));
                } elseif (
$this->Session->check("$this->_sessionKey.$this->_currentStep")) {
                    
$this->controller->data $this->read($this->_currentStep);
                }
            
                
$prepareCallback '_' Inflector::variable('prepare_' $this->_currentStep);
                if (
method_exists($this->controller$prepareCallback)) {
                    
$this->controller->$prepareCallback();
                }
                
                
$this->config('activeStep'$this->_currentStep);    
                return 
$this->controller->render($this->_currentStep);
            } else {
                
trigger_error(__('Step validation: ' $step ' is not a valid step.'true), E_USER_WARNING);
            }
        }
    
        if (
$step != 'reset' && $this->autoReset) {
            
$this->resetWizard();
        }

        
$this->redirect();
    }
/**
 * Selects a branch to be used in the steps array. The first branch in a group is included by default.
 *
 * @param string $name Branch name to be included in steps.
 * @param boolean $skip Branch will be skipped instead of included if true.
 * @access public
 */    
    
function branch($name$skip false) {    
        
$branches = array();
        
        if (
$this->Session->check($this->_branchKey)) {
            
$branches $this->Session->read($this->_branchKey);
        }
        
        if (isset(
$branches[$name])) {
            unset(
$branches[$name]);
        }
        
        
$value $skip 'skip' 'branch';
        
$branches[$name] = $value;
        
        
$this->Session->write($this->_branchKey$branches);
    }
/**
 * Saves configuration details for use in WizardHelper or returns a config value. 
 * This is method usually handled only by the component.
 *
 * @param string $name Name of configuration variable.
 * @param mixed $value Value to be stored.
 * @return mixed 
 * @access public
 */    
    
function config($name$value null) {
        if (
$value == null) {
            return 
$this->Session->read("$this->_configKey.$name");
        }
        
$this->Session->write("$this->_configKey.$name"$value);
    }
/**
 * Get the data from the Session that has been stored by the WizardComponent.
 *
 * @param mixed $name The name of the session variable (or a path as sent to Set.extract)
 * @return mixed The value of the session variable
 * @access public
 */
    
function read($key null) {
        if (
$key == null) {
            return 
$this->Session->read($this->_sessionKey);
        } else {
            
$wizardData $this->Session->read("$this->_sessionKey.$key");
            if (!empty(
$wizardData)) {
                return 
$wizardData;
            } else {
                return 
null;
            }
        }
    }
/**
 * Handles Wizard redirection. A null url will redirect to the "expected" step.
 *
 * @param mixed $url Stepname to be redirected to.
 * @access public
 */
    
function redirect($step null$status null$exit true) {
        if (
$step == null) {
            
$step $this->_getExpectedStep();
        }

        
$url $this->wizardAction $step;
        
        
$this->controller->redirect($url$status$exit);
    }
/**
 * Resets the wizard by deleting the wizard session.
 *
 * @access public
 */    
    
function resetWizard() {
        
$this->Session->del($this->_branchKey);
        
$this->Session->del($this->_sessionKey);
    }
/**
 * Saves the data from the current step into the Session.
 *
 * Please note: This is normally called automatically by the component after 
 * a successful processCallback, but can be called directly for advanced navigation purposes.
 *
 * @access public
 */        
    
function save() {
        
$this->Session->write("$this->_sessionKey.$this->_currentStep"$this->controller->data);
    }
/**
 * Removes a branch from the steps array.
 *
 * @param string $branch Name of branch to be removed from steps array.
 * @access public
 */    
    
function unbranch($branch) {
        
$this->Session->del("$this->_branchKey.$branch");
    }
/**
 * Finds the first incomplete step (i.e. step data not saved in Session).
 *
 * @return string $step or false if complete
 * @access protected
 */    
    
function _getExpectedStep() {
        foreach (
$this->steps as $step) {
            if (!
$this->Session->check("$this->_sessionKey.$step")) {
                
$this->config('expectedStep'$step);    
                return 
$step;
            }
        }
        return 
false;
    }
/**
 * Saves configuration details for use in WizardHelper.
 *
 * @return mixed
 * @access protected
 */        
    
function _branchType($branch) {
        if (
$this->Session->check("$this->_branchKey.$branch")) {
            return 
$this->Session->read("$this->_branchKey.$branch");
        }
        return 
false;
    }
/**
 * Parses the steps array by stripping off nested arrays not included in the branches
 * and returns a simple array with the correct steps. 
 *
 * @param array $steps Array to be parsed for nested arrays and returned as simple array.
 * @return array
 * @access protected
 */    
    
function _parseSteps($steps) {
        
$parsed = array();

        foreach (
$steps as $key => $name) {
            if (
is_array($name)) { 
                foreach (
$name as $branchName => $step) {
                    
$branchType $this->_branchType($branchName);

                    if (
$branchType) {
                        if (
$branchType !== 'skip') {
                            
$branch $branchName;
                        }
                    } elseif (empty(
$branch) && $this->defaultBranch) {
                        
$branch $branchName;
                    }
                }
                
                if (!empty(
$branch)) {
                    if (
is_array($name[$branch])) {
                        
$parsed array_merge($parsed$this->_parseSteps($name[$branch]));
                    } else {
                        
$parsed[] = $name[$branch];
                    }
                }
            } else {
                
$parsed[] = $name;
            }
        }
        return 
$parsed;
    }
/**
 * Moves internal array pointer of $this->steps to $step and sets $this->_currentStep.
 *
 * @param $step Step to point to.
 * @access protected
 */        
    
function _setCurrentStep($step) {
        
$this->_currentStep reset($this->steps);
        
        while(
current($this->steps) != $step) {
            
$this->_currentStep next($this->steps);
        }
    }
/**
 * Validates controller data with the correct model if the model is included in
 * the controller's uses array. This only occurs if $autoValidate = true and there
 * is no processCallback in the controller for the current step.
 *
 * @return boolean
 * @access protected
 */    
    
function _validateData() {
        
$controller =& $this->controller;
        
        foreach (
$controller->data as $model => $data) {
            if (
in_array($model$controller->uses)) {
                
$controller->{$model}->set($data);
                
                if (!
$controller->{$model}->validates()) {
                    return 
false;
                }
            }
        }
        return 
true;
    }
/**
 * Validates the $step in two ways:
 *   1. Validates that the step exists in $this->steps array.
 *   2. Validates that the step is either before or exactly the expected step.
 *
 * @param $step Step to validate.
 * @return mixed
 * @access protected
 */        
    
function _validStep($step) {
        if (
in_array($step$this->steps)) {
            if (
$this->lockdown) {
                return (
array_search($step$this->steps) == array_search($this->_getExpectedStep(), $this->steps));
            }
            return (
array_search($step$this->steps) <= array_search($this->_getExpectedStep(), $this->steps));
        }
        return 
false;
    }
}
?>

 

Comments 773

CakePHP Team Comments Author Comments
 

Comment

1 Nice update, thanks!

Tried the new version today. Nice update. Feels a bit more solid than before.
Posted Oct 27, 2008 by Martin Westin
 

Comment

2 Nice

But How to use this? Can you provide some example?? please.
Posted Oct 28, 2008 by wispoz
 

Comment

3 New Tutorial

But How to use this? Can you provide some example?? please.
wispoz, the tutorial was just submitted. Hopefully it will be up in the next couple days.
Posted Nov 6, 2008 by jaredhoyt
 

Question

4 Will it works with files uploading?

Hi, i've not read the tutorial and haven't tried the component yet, but if it's not difficult to you answer please.
Posted Dec 10, 2008 by Alexander
 

Comment

5 File Uploading

Hi, i've not read the tutorial and haven't tried the component yet, but if it's not difficult to you answer please.
I am currently using the wizard to handle file uploading and it handles files in the same way as a normal form.
Posted Dec 10, 2008 by Penfold
 

Comment

6 admin routing

Nice component jared. Working like a charm.
Any special tweaks to use it with admin routing? I want to make a wizard in the app backend.

I found a solution. I'm using
Router::connect('/admin/addproduct', array('controller' => 'products', 'action' => 'wizard', 'admin' => 1)); in my routes.
Posted Dec 15, 2008 by Alex Ciobanu
 

Comment

7 capturing image inputs

This component has been a great time saver, thanks!

One thing I ran into was that the checks for Cancel and Previous clicks in a form won't work if the input buttons are an image type. I simply added the Previous_x and Cancel_x to the form click checks.
Posted Feb 20, 2009 by Barrett Kendjoria
 

Comment

8 Re: capturing image inputs

This component has been a great time saver, thanks!

One thing I ran into was that the checks for Cancel and Previous clicks in a form won't work if the input buttons are an image type. I simply added the Previous_x and Cancel_x to the form click checks.

Thanks for the bug find! I was evaluating with empty() on params['form']['Cancel'] and ['Previous'] expecting name and value to both be present. I didn't think about image submit buttons. This has been changed to use isset.
Posted Mar 7, 2009 by jaredhoyt
 

Comment

9 Causes My Apache to Crash

I have downloaded the latest Wizard code and advancing to the next step in my application causes apache to crash. Everytime. If the validation fails, everything is fine. But if it succeeds and attempts to load the next step, apache will crash. Any thoughts? I am running cake 1.2 on WAMP server 2.0. Note that it does not crash using previous version of wizard code.
Posted Mar 10, 2009 by Shane
 

Comment

10 Re: Causes My Apache to Crash

Shane,

Have you checked your Apache errors logs?
Posted Mar 25, 2009 by jaredhoyt
 

Comment

11 Branching

Hello, ive pasted some code in the bin,

when i have the follwoing code setup it does not work as expected.

http://bin.cakephp.org/view/670997522
fyi i am using all the default settings.

Basiccaly the way i want it to work is that if im doing a wizard pertaining to a certain product i want it to branch into the payment process , otherwise i just want it to finish up.

Currently its ALWAYS going into that process_payment branch, i have also tried skipping, using

$this->Wizard->branch('process_payments' , true );

and unbranching.

Posted Mar 30, 2009 by Arnold Almeida
 

Comment

12 Re: branching

Basically the way i want it to work is that if im doing a wizard pertaining to a certain product i want it to branch into the payment process, otherwise i just want it to finish up.

Currently its ALWAYS going into that process_payment branch, i have also tried skipping, using

$this->Wizard->branch('process_payments' , true );

and unbranching.

Arnold,

Here are two solutions for you:

1. Use $defaultBranch = false; (it defaults to true) in your beforeFilter() and Wizard->branch('process_payment') if you want to use that branch.

2. Use the branch skip feature: Wizard->branch('process_payment', true);

Explanations:

1. The Wizard by default will always use the first branch in a branch group (unless $defaultBranch = false). Using unbranch() does not do anything for this, unbranch() is only to remove a branch you've previously included with branch(). By setting $defaultBranch = false, you will be able to branch only to those branches you want to use (1 per branch group).

2. I noticed both in your comment and in your bin paste that your branch was named 'process_payment' but all of your branching actions used branch('process_payments').

This may be as simple as a typo, but I figured I'd offer a more detailed explanation of the PBN. I still consider the PBN aspect of the WizardComponent to be "beta" so it's very probable there are bugs & poorly named features. :D

Hope this helps,
jaredhoyt
Posted Mar 31, 2009 by jaredhoyt
 

Comment

13 Feedback

Hi Jared,

Got some feedback for you.

I tried using your suggesting buy i ran into some limitations. I ended up solving my problem by switching b/w the current id to determine the steps i would be using.

/*
*Method 1
*/
Set the dafault branch to false via in the beforeFilter
$this->Wizard->defaultBranch = false

//outcomes
Skips the branch as expected
but when expected to hook into my branch (using 'process_payment' or 'billing_and_delivery' ) it does not.

/*
*Method 2
*/
Skipping the branch goes into a loop when there is no step after the "skipped branch" however if i add a "test" step it works as expected

Is this on github or something similar? as i wouldnt mnind forking it and adding some contributions.

Thanks for your great work.

Arnold

Posted Mar 31, 2009 by Arnold Almeida
 

Comment

14 Two Suggestions for Improvements

Awesome component idea! This is going to come in handy. With that said, I have two suggestions for improvement.

1. Internationalization Improvement


Utilize sprintf in conjunction with %s/%d/etc. placeholders in your string. This way you only have to convert one string in LC_MESSAGES instead of multiple similar strings.

For example, I changed this:

trigger_error(__('Process Callback not found. Please create Controller::' . $processCallback, true), E_USER_WARNING);
...to this:

trigger_error(sprintf(__('Process Callback not found. Please create Controller::%s', true), $processCallback), E_USER_WARNING);
Similarly, I changed this:

trigger_error(__('Step validation: ' . $step . ' is not a valid step.', true), E_USER_WARNING);
...to this:

trigger_error(sprintf(__('Step validation: %s is not a valid step.', true), $step), E_USER_WARNING);

2. View Rendering Improvement


Several of my prepare steps simply reuse existing views via Controller::render(). Typically, this prevents a view from autoRendering in CakePHP. I would recommend the WizardComponent do the same by not autoRendering if a view has already been rendered.

I did this by changing this line of the Component:

return $this->controller->render($this->_currentStep);
...to this:

return $this->controller->autoRender ? $this->controller->render($this->_currentStep) : true;
Posted Apr 12, 2009 by Matt Huggins
 

Bug

15 Not working for AJAX forms

Hi,

I had the wizard working perfectly but than had to change it to AJAX. Then something goes:

When completing step one, it will post via AJAX instead of a regular HTTP Post and then the url for the redirect isn't working as expected (it is misschien the controller). I ried to change it to a nice array still with autodetecting the current controller, but that made an infinite loop.

Can you fix the redirect function so that it uses the full path to the controller?


BTW. What is the easiest way to get all the data in the _afterComplete function as Model data? Now I re-model it myself because of the extra step layers.
Posted Aug 6, 2009 by sylvain
 

Comment

16 Form URL correction

The suggested way to create forms for the Wizard Component gave me some trouble when I had to place my app in a folder down from the top of the domain (i.e. in a shared hosting situation).

Basically, creating the form using $this->here

$form->create('Signup',array('id'=>'SignupForm','url'=>$this->here));
causes an incorrect url to be created for the form action if Cake's webroot is not '/'.

I was able to resolve this by adding a variable to the view with a preformed url for the form. The easiest way is to do this by creating a beforeRender method in wizard.php:


/**
 * Adds wizard variable to view
 * Usage: 
 * $form->create(false, array('url'=>$wizard['form_url']));
 *
 * @access public
 */
    function beforeRender() {
        $wizard = array();
        $wizard['form_url'] = array(
            'controller'=>$this->controller->name,
            'action'=>$this->wizardAction,
            current($this->steps)
        );
        $this->controller->set('wizard', $wizard);
    }


Once this is in place, change the form creation in each view to use the new variable:


$form->create('Signup',array('id'=>'SignupForm','url'=>$wizard['form_url']));
Posted Aug 9, 2009 by VincentM
 

Comment

17 Re: Not working for AJAX forms

Can you fix the redirect function so that it uses the full path to the controller?
My post above is probably what you need. I started out trying to debug the redirects, but that turned out not to be the problem.

BTW. What is the easiest way to get all the data in the _afterComplete function as Model data? Now I re-model it myself because of the extra step layers.
Try adding this code to wizard.php. This works, though could probably be improved.


/**
 * Get the data from the Session that has been stored by the WizardComponent by model (instead of by step).
 *
 * @param mixed $name The name of the model
 * @return mixed The value of the session variable
 * @access public
 */
    function readModel($name) {
        $result = array();
        if (App::import('Model', $name)) {
            $model = new $name;
            $fields = $model->schema();
            foreach (array_keys($fields) as $field) {
                $result[$field] = null;
            }
        }
        $data = $this->read();
        foreach($data as $k=>$v) {
            if (isset($v[$name])) {
                $result = array_merge($result, $v[$name]);
            }
        }
        return $result;
    }
Posted Aug 9, 2009 by VincentM
 

Bug

18 PBN - different payments

The steps I'm trying to accomplish is to have different forms in case of different payment methods.
I do get account info, to which a user want to partecipant, review if everything is correct, then go to billing to let the user choose the way he wants to pay and the process the payment specific code.

        $this->Wizard->steps = array(
            'account', 
            'event',
            'review',
            'billing',
            array('pay'=>array('paypal')),
            array('ban'=>array('bank')),
            array('cre'=>array('creditcard')),
            array('cas'=>array('cash')),
            array('pos'=>array('postal'))
        );
In the _processBilling, I have some conditions in order to branch differently in case I have selected different PaymentMethod's id:

            if ($this->data['PaymentMethod']['id']==1) {
                debug('Brancing to bank');
                $this->Wizard->branch('ban');
                return true;
            } else if ($this->data['PaymentMethod']['id']==2) {
                debug('Brancing to paypal');
                $this->Wizard->branch('pay');
                return true;
            } else if ($this->data['PaymentMethod']['id']==3){
                debug('Brancing to creditcard'); 
                $this->Wizard->branch('cre');
            } else if ($this->data['PaymentMethod']['id']==4){
                debug('Brancing to postal'); 
                $this->Wizard->branch('pos');
            } else if ($this->data['PaymentMethod']['id']==5){
                debug('Brancing to cash'); 
                $this->Wizard->branch('cas');
            } else {
                debug('Hey, I will not branch anywhere!');
                return false;
            }
            return true;

Unfortunately the wizard goes directly to the "completeUrl" and does not sends the user to one of the branches...
Any idea ?

PS: I'm getting an headache on this now :)
Posted Nov 23, 2009 by Julien Buratto
 

Comment

19 Anyone having branch headaches

Figured I would paste this snippet, I finally figured out how I could use this successfully as I was having issues trying to do a custom validation on the form to have it select where to branch off too.

http://bin.cakephp.org/saved/53100
P.S. Julien, I think you might have an issue, can you post a bin of your full function code for that? Otherwise I think this might be the issue:


  if ($this->data['PaymentMethod']['id']==1) { 
                debug('Brancing to bank'); 
                $this->Wizard->branch('ban'); 
                return true; 
            } else if ($this->data['PaymentMethod']['id']==2) { 
                debug('Brancing to paypal'); 
                $this->Wizard->branch('pay'); 
                return true; 
            } else if ($this->data['PaymentMethod']['id']==3){ 
                debug('Brancing to creditcard');  
                $this->Wizard->branch('cre'); 
            } else if ($this->data['PaymentMethod']['id']==4){ 
                debug('Brancing to postal');  
                $this->Wizard->branch('pos'); 
            } else if ($this->data['PaymentMethod']['id']==5){ 
                debug('Brancing to cash');  
                $this->Wizard->branch('cas'); 
            } else { 
                debug('Hey, I will not branch anywhere!'); 
                return true; //this allows it to pass to the next step if nothing is chosen. 
            } 
            return false; //This shouldn't pass to the next step, therefore return false.
Posted Nov 24, 2009 by uniacid
 

Comment

20 noted issue

Just a note:

I also had issues when trying to access the form data from the _process function, I used the proper format I believe of the stepname.model.field
so not sure why it's not able to pick it up, instead I had to use good ole $_POST

Any ideas why this could be?


$custom = $_POST['data']['Order']['ForkGeometryCustomFrameSize'];
            
//$this->Wizard->read('Frametype.Order.ForkGeometryCustomFrameSize'); Doesnt Work!?!?!?

$standard = $_POST['data']['Order']['ForkGeometryStandardFrameSize'];

//$this->Wizard->read('Frametype.Order.ForkGeometryStandardFrameSize'); Doesnt Work!?!?!1
Posted Nov 24, 2009 by uniacid
 

Comment

21 Re: noted issue

Just a note:

I also had issues when trying to access the form data from the _process function, I used the proper format I believe of the stepname.model.field
so not sure why it's not able to pick it up, instead I had to use good ole $_POST

Any ideas why this could be?


$custom = $_POST['data']['Order']['ForkGeometryCustomFrameSize'];
            
//$this->Wizard->read('Frametype.Order.ForkGeometryCustomFrameSize'); Doesnt Work!?!?!?

$standard = $_POST['data']['Order']['ForkGeometryStandardFrameSize'];

//$this->Wizard->read('Frametype.Order.ForkGeometryStandardFrameSize'); Doesnt Work!?!?!1

This is because form data isn't instantly stored in the Wizard Session in a _process callback. You access your data in _process callback as you normally would a form - $this->data. It's only after the callback is complete that the data is moved into the Session. $this->Wizard->read() is used for accessing data from previous steps, not the one that was just submitted.
Posted Dec 20, 2009 by jaredhoyt