Skip to content

Instantly share code, notes, and snippets.

@tom--
Created March 25, 2015 13:53
Show Gist options
  • Select an option

  • Save tom--/94b67846991a381f73ca to your computer and use it in GitHub Desktop.

Select an option

Save tom--/94b67846991a381f73ca to your computer and use it in GitHub Desktop.
Controller class for Yii 2 to support a wizard using one form model and several actions with branching logic.
<?php
namespace spinitron\controllers;
use Yii;
use yii\web\Controller;
use yii\web\Session;
class WizardController extends Controller
{
/**
* @var \yii\base\Model Class name of the Wizard's form model
*/
static $formClass;
/**
* @var string Route of the first form of the wizard.
*/
static $startRoute = 'index';
/**
* @var Session
*/
protected $session;
/**
* @var string
*/
protected $step;
/**
* @var array
*/
protected $attributes;
public function beforeAction($action)
{
if (!parent::beforeAction($action)) {
return false;
}
$this->session = Yii::$app->session;
if (!$this->session->isActive) {
$this->session->open();
}
if ($this->session->has('step')) {
$this->step = $this->session->get('step');
$this->attributes = $this->session->get('attributes');
} else {
// Just being extra careful...
$this->session->remove('attributes');
}
return true;
}
/**
* Clear session state and redirect to start of wizzard.
*/
public function startOver()
{
$this->session->remove('step');
$this->session->remove('attributes');
$this->redirect([static::$startRoute]);
}
/**
* Create a form model and process it for the $current step of the wizzard.
*
* Redirect to $next on success, return form model with errors on validation error.
*
* @param string $current Scenario of current action
* @param string|callable|bool $next Route to redirect to on success. If callable, it
* takes the form model as argument and returns a (string) route, or it can redirect.
* Set false to return the $form without redirecting.
*
* @return \yii\base\Model Form model with validation errors
*/
public function doForm($current, $next)
{
/** @var \yii\base\Model $form */
$form = new static::$formClass(['scenario' => $current]);
if ($this->attributes !== null) {
foreach ($this->attributes as $key => $value) {
$form->$key = $value;
}
}
$loaded = $form->load(Yii::$app->request->post());
if ($loaded && $form->validate()) {
$this->session->set('attributes', $form->toArray());
$this->session->set('step', $current);
if ($next !== false) {
$this->redirect([is_callable($next) ? call_user_func($next, $form) : $next]);
}
}
return $form;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment