Having just solved a very similar problem, I would suggest the following pseudocode. What it boils down to is using the query object to pass parameters to the other runmodes.
sub join {
# This is the 'join' runmode
my $self = shift;
my $q = $self->query;
# It submits to the verify runmode
if ($self->query->param('error')) {
# We just tried to submit, but had error(s); print them
}
# Print the rest of the form, etc
}
sub verify {
# 'verify' runmode
my $self = shift;
my $q = $self->query;
# Do error checking
unless (@errors) {
# This is how we 'redirect' without redirecting.
$q->param('username',$username);
$q->param('password',$password);
return $self->create;
} else {
$q->param(-name => 'error', -value => \@errors);
return $self->join;
}
}
sub create {
# 'create' runmode
my $self = shift;
my $q = $self->query;
# Create the account
return $self->viewprofile;
}
sub viewprofile {
# 'viewprofile' runmode
# ..uses $q->param('username') which is either supplised by the user
+, or
# by the code in 'verify', which was passed to 'create' and then on
# to us.
}