I fear that giving the complete answer to this quesiton will only show the kind of deludged curmudgeon I am.
So I'm working on a web project. I'm working with CGI::Application. I want to use Apache::Session (or SessionX, whatever) to do my sessioning stuff. I want to retrieve my session in the setup stage, and then just haul its ass around to whatever run-modes I need via the $self.
Now, $self->param within CGI::Application could do the job, a la:
sub setup {
my $self = shift;
tie %session, 'Apache::Session', $self->query->cookie('session_id'
+);
$self->param('session', \%session);
# etc.
}
sub current_run_mode {
my $self = shift;
# etc.
my $uid = $self->param('session')->{uid};
# etc.
}
I'm willing to do this, if need be. But I like my composited objects (and their related methods) to be "first class". In this case, that means I'd rather my attempts to get session data would look like:
my $uid = $self->session->uid;
How would I do this? (Rhetorical question.) I have already subclassed CGI::Application to My::CGIApplication that gives me 1st class object composition capabilities, like this:
sub setup {
my $self = shift;
tie %session, 'Apache::Session', $self->query->cookie('session_id'
+);
$self->composite_object( name => 'session',
object => tied(%session));
# etc.
}
This gives me calls like $self->session. So now I need to get at the session data in a first class way. (Obviously I could get at it in a 2nd or 3rd class way such as $self->session->FETCH('uid'), but I don't like the smell of this.)
So, this leads me to subclassing Apache::Session. Consider My::ApacheSession which has within it this...
sub AUTOLOAD {
my $self = shift;
my $attribute = $AUTOLOAD;
$method =~ s/.*:://;
if ( length($method) != 0 ) {
if ( @_ > 1) {
return $self->STORE($attribute, @_);
} else {
return $self->FETCH($attribute);
}
} else {
croak "No such object attribute referenced by name '"
. $attribute
. ' to provide ";
}
}
So this is entirely doable. However, I would like it cleaner (i.e. forgetting about FETCH and STORE). So refer back to my original posting...
sub AUTOLOAD {
my $self = shift;
my $attribute = $AUTOLOAD;
$method =~ s/.*:://;
my %session = Foo($self);
if ( @_ > 1) {
return $session{$attribute} = $_[0];
} else {
return $session{$attribute};
}
}
So that's all. Hope with all that wind-up it wasn't an anticlimax. Perrin, as you said, there is another way. I was just hoping that the way I wanted to do things exists, too.
Cheers,
Richard
|