Easy Multi Page Forms (or Wizards) with CakePHP

February 16, 2010 by Adam · Leave a Comment 

There is a wizard component available for CakePHP that’s been around for a very long time, however it uses a lot of code to something that doesn’t really need it. Today I needed to spread a single form across multiple pages for an app I am writing.

Here is the very simple controller action I used to achieve it:

<?php
	function add($step = 'account') { // $step is your first page

		$order = array(
			'contact_name' => $this->Auth->user('contact_name'),
			'company_name' => $this->Auth->user('company_name'),
			'account_number' => $this->Auth->user('account_number'),
			'delivery_address' => $this->Auth->user('delivery_address'),
			'invoice_address' => $this->Auth->user('invoice_address'),
			'promotional_discount' => $this->Auth->user('promotional_discount'),
			'extra_ordinary_discount' => $this->Auth->user('extra_ordinary_discount')
		); // your defaults

		if($this->Session->check('order')) {
			$order = Set::merge($order, $this->Session->read('order'));
		}

		if(!empty($this->data)) {
			$this->data['Order'] = Set::merge($order, $this->data['Order']);

			if($step == 'thanks') { // $step is your last step
				if(!$this->Order->save($this->data)) {
					$this->Session->setFlash('There was an error trying to save your order,
						please make sure you completed all steps');
					$step = 'confirm'; // $step is your last-but-one step
				}
			}
		} else {
			$this->data['Order'] = $order;
		}

		$this->Session->write('order', $this->data['Order']);

		$this->render('add' . DS . $step); //put your files in a folder and name them after the matching step, no need for validation, cakephp will 404 on any missing steps

	}
?>

Then in your view, post your form to the next page, so the accounts page posts to /orders/add/range, the range form posts to /orders/add/items and so on. You can then provide user navigation between the steps just by linking to that page.

<div id="page" class="accountinfo">
	<?php
		echo $this->Form->create('Order', array('url' => '/orders/add/range'));
		echo $this->Form->input('contact_name');
		echo $this->Form->input('company_name');
		echo $this->Form->input('account_number');
		echo $this->Form->input('order_number');
		echo $this->Form->input('date_required');
	?>
	<div id="paging">
		<?php echo $this->Html->link('Previous', array('controller' => 'orders', 'action' => 'index')); // first step so previous takes you back to the index ?>
		<?php echo $this->Form->submit('Next'); ?>
	</div>
	<?php echo $this->Form->end(); ?>
</div> <!-- page -->

I don’t think I could make this any simpler!

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks

Related posts:

  1. Integrating the Auth Component with a bespoke 3rd party Single Sign-On Service in CakePHP
  2. Simple Sluggable Behavior for CakePHP

About Adam
Adam is senior developer for Image+ Ltd in Coventry, England. He has been developing websites for over 10 years, and currently freelances through his own company, Votive Media. Follow him on twitter for more!

Comments are closed.