As an experiment, I converted the PRADO hangman example to use GET based state propagation with WACT controllers instead of viewstate.
First, you describe your input parameters, associating them with controller nodes:
PHP Code:
$game->addParameter(new GetParameter('level', 'game.level'));
$game->addParameter(new GetParameter('word', 'game.word'));
$game->addParameter(new GetParameter('guesses', 'game.guesses'));
$game->addParameter(new GetParameter('misses', 'game.misses'));
$guess->addParameter(new GetParameter('letter'));
The first parameter to GetParameter is the name. The last line is equivalent to $_GET['letter']. The second parameter is a location in the response model to bind the input parameter to. Because the input parameter is bound to the model, when we generate links back into the application, we can automatically apply those bound parameters without specifying them.
In the view, you can generate a link with :
PHP Code:
$guess =& new LinkTransition(
$this->dataRoot->data, $this->dataParent->data,
$this->root->controller, '/game/play/guess');
$guess->build();
<a href="<?= $guess->getHREF() ?>"></a>
This code generates an url like:
Code:
http://localhost/examples/apps/hangman/index.new.php/play/guess?letter=C&misses=0&guesses=&word=ACCOUNT&level=10
The first parameter to the LinkTransition constructor specifies the response model where bound input parameters can be found. In this case "level", "word", "guesses", and "misses". The second parameter specifies where unbound parameters can be found. In this case, "guess". The third parameter specifies a controller and the fourth parameter specifies a specific command on the controller: "/game/play/guess".
Note that the controllers are hierarchical. The guess parameter is associated with the guess controller, which is a command. The rest of the parameters are associated with the parent game controller which mostly exists to define the game state. ("All my children use these parameters.")
You can also think of this url like a function call:
PHP Code:
/game/play/guess( $level, $word, $guesses, $misses, $guess);
The LinkTransition is intelligent about default values and can shorten the URL generated when a default can be used. That is why there is no 'game/' prefix on the generated URL.
Using a template, there is a tag specifically for creating links:
Code:
<front:link command="/game/play/guess">{$letter}</front:link>
This generates the exact same URL as above in the context of the template. Notice the $letter is the same as the letter parameter. These are both in the unbound parameter DataSource, but not otherwise related. The proper values of all five parameters can be deduced from the context where this is used and their controller definitions.
Additionally, there is some optimization available to the template compiler. The template compiler can resolve many of the lookups at compile time. The code generated by the template compiler looks very much like the familiar:
PHP Code:
echo '<a href="index.php?letter=', $letter, '">', $letter, '</a>';
Only a bit more complicated and with all the parameters, not just letter. The key point being that the LinkTransition class is not required inside of a compiled template.
The same principles can be applied to other types of input. Each type of input is called a channel. A LinkTransition has two available channels: GET and PATHINFO. A FormTransition adds POST. Other channels are possible, like COOKIE.
An interesting case might be to create a CLI channel for parsing command line parameters. A weird consequence of this is that you could end up with a CLITransition class that could generate new CLI calls back into your application that preserve state. ("hangman -word account -guesses -misses 0 -level 10 guess A")
Bookmarks