Re: Wizards and MVC
Posted: Fri Jan 28, 2011 9:58 am
Another way to look at it, is that a Wizard is just a paginated form.
A community of PHP developers offering assistance, advice, discussion, and friendship.
http://forums.devnetwork.net/
That's only the "linear" wizard, IMHOJenk wrote:Another way to look at it, is that a Wizard is just a paginated form.
I imagine he is refering to "wizards" where steps are not required to be completed sequentially.Jenk wrote:There's another type of wizard?
I think paginated forms is a simple way to view a wizard (and not a bad one necessarily) . However there are a number of cases where there are either multiple paths through a sequence or where certain steps can be skipped. I gave the checkout process as a place where I often use an Application Controller. Here are some examples of the non-linear cases I mentioned using checkout as a use case.Jenk wrote:There's another type of wizard?
In homepage, Router checks if there is controller selected in URL. If isn't, script gets default controller from configuration file and instantiates it. If method for controller is not set, it loads $controller->index() method. If not, loads: $controller->$selected_method();VladSun wrote:How do you guys write your wizard pages in a way that fits the MVC approach? I'm not interested in passing the current model state. I'm more interested in the M-V-C relations defined.
The problem I'm facing is that the Controller doesn't know the logic flow to follow - it's in the Model.
Code: Select all
class Blog // implements Controller; extends Controller
{
public function index()
{
$this->get_view('blog_index');
}
public function new_post()
{
$this->get_view('blog_new_post');
}
public function get_post($id = null)
{
if (!is_null($id))
{
$this->get_model('My_Model');
$this->my_model->get_post_by_id($id);
$this->variables['posts'] = $this->my_model->get_post_by_id($id);
/**
* View file:
*
* foreach ($this->variables as $variable => $key)
* return $key
*/
$this->get_view('blog_get_post');
}
}
}Code: Select all
this.configurator = new Ext.App.Model.Configurator();
this.wizard = new Ext.ex.Wizard.Panel(
{
configurator : this.configurator,
router : new Ext.ex.Wizard.Router(
{
map :
[
{
object : new Ext.App.Component.Wizard.Stage.FileUpload(),
stages :
[
{
object : new Ext.App.Component.Wizard.Stage.SchemaInfo()
},
{
object : new Ext.App.Component.Wizard.Stage.TablesPicker()
},
{
object : new Ext.App.Component.Wizard.Stage.RelationsEditor()
}
]
}
]
})
});Code: Select all
Ext.ex.Wizard.Stage.Component = function(config)
{
Ext.apply(this, config);
Ext.ex.Wizard.Stage.Component.superclass.constructor.call(this, config || {});
this.addEvents(
{
stageInitialized : true,
stagePrepared : true,
stageCancelled : true,
stageCompleted : true,
stageFailed : true,
stageReady : true
});
}
Ext.extend(Ext.ex.Wizard.Stage.Component, Ext.Panel,
{
model : null,
init : function (model)
{
this.model = model;
this.fireEvent('stageInitialized', true, this);
},
prepare : function ()
{
this.fireEvent('stagePrepared', true, this);
},
redraw : function ()
{
},
process : function ()
{
this.fireEvent('stageCompleted', true, this);
},
cancel : function ()
{
this.reset();
this.fireEvent('stageCancelled', true, this);
},
reset : function ()
{
}
});Code: Select all
interface IStage
{
function setModel($model);
function preWizardInit(); // check for some preconditions met before the Wizard starts. Run at Wizard init.
function didPreWizardInitSucceeded(); // shell we run the Wizard at all?
function preProcess(); // check for some condtions (together with $model current data). Run "before" stage.
function didPreProcessSucceeded(); // Stage has errors? If yes Wizard stops - Next not available, Prev available
function isStageSilent(); // Does Stage need a View or it may process silently then jumping to the next stage
function isStageRequired(); // Is Stage required at all, if not all substages are not required either.
function process(); // If isStageRequired == true, execute this method
function didProcessSucceeded(); // Stage has Errors?
}Code: Select all
class Router
{
public function setMap($map);
public function setStateManager($stateManager);
public function getNextStage(); // returns IStage
}Code: Select all
class Wizard extends ActionController
{
public function __construct($router, $stateManager);
public function nextStage();
public function finish();
}Code: Select all
class MyWizard extends Wizard
{
public function __construct()
(
parent::__construct
(
new Router
(
array
(
array
(
'stage' => new Stage1(),
'substages' => array
(
array
(
'stage' => new Stage1_1(),
'substages' => null
),
array
(
'stage' => new Stage1_2(),
'substages' => array
(
'stage' => new Stage1_2_1(),
'substages' => null
),
),
)
),
array
(
'stage' => new Stage2(),
'substages' => null
),
)
),
new StateManager()
);
)
}