18.2 Sharing Data Between Various Handlers

Sometimes you want to set some data in one of the early handler phases and make it available in the latter handlers. For example, say you set some data in a TransHandler and you want the PerlHandler to be able to access it as well.

To accomodate this, Apache maintains a "notes" table (tables are implemented by the Apache::Table module) in the request record. This table is simply a list of key/value pairs. One handler can add its own key/value entry to the notes table, and later the handler for a subsequent phase can retrieve the stored data. Notes are maintained for the life of the current request and are deleted when the transaction is finished. The notes( ) method is used to manipulate the notes table, and a note set in one Apache module (e.g., mod_perl) can later be accessed in another Apache module (e.g., mod_php).

The notes( ) method accepts only non-reference scalars as its values, which makes this method unfit for storing non-scalar variables. To solve this limitation mod_perl provides a special method, called pnotes( ), that can accept any kind of data structure as its values. However, the data set by pnotes( ) is accessible only by mod_perl.

The note gets set when the key/value pair is provided. For example, let's set a scalar value with a key foo:

$r->notes("foo" => 10);

and a reference to a list as a value for the key bar:

$r->pnotes("bar" => [1..10]);

Notes can be retrieved in two ways. The first way is to ask for the value of the given key:

$foo = $r->notes("foo");

and:

@bar = @{ $r->pnotes("bar") || [  ] };

Note that we expect the note keyed as bar to be a reference to a list.

The second method is to retrieve the whole notes table, which returns a hash reference blessed into the Apache::Table class:

$notes = $r->notes( );
$foo   = $notes->{foo};

and:

$pnotes = $r->pnotes( );
@bar    = @{ $pnotes->{bar} || [  ] };

Apache modules can pass information to each other via the notes table. Here is an example of how a mod_perl authentication handler can pass data to a mod_php content handler:

package Book::Auth;
...
sub handler {
    my $r = shift;
...
    $r->notes('answer',42);
...
}
1;

The mod_php content handler can retrieve this data as follows:

...
$answer = apache_note("answer");
...

You can use notes along with the subrequest methods lookup_uri( ) and lookup_filename( ), too. To make it work, you need to set notes in the subrequest object. For example, if you want to call a PHP subrequest from within mod_perl and pass it a note, you can do it in the following way:

my $subr = $r->lookup_uri('wizard.php');
$subr->notes('answer' => 42);
$subr->run;

As of the time of this writing you cannot access the parent request tables from a PHP handler; therefore, you must set this note for the subrequest. If the subrequest is running in the mod_perl domain, however, you can always keep the notes in the parent request notes table and access them via the main( ) method:

$r->main->notes('answer');

Similarly to the notes, you may want or need to use the Apache environment variables table to pass the information between different handlers.

If you know what environment variables you want to set before the server starts and you know their respective values, you can use SetEnv and PerlSetEnv in httpd.conf, as explained in Chapter 4. These settings will always be the same for all requests.

However, if you want to change or add some of the environment variables during the processing of a request, because some other handler that will be executed later relies on them, you should use the subprocess_env( ) method.

<!--#if expr="$hour > 6 && $hour < 12" -->
Good morning!
<!--#elif expr="$hour >= 12 && $hour <= 18" -->
Good afternoon!
<!--#elif expr="$hour > 18 && $hour < 22" -->
Good evening!
<!--#else -->
Good night!
<!--#endif -->

and you have the following code in your mod_perl handler:

my $hour = (localtime)[2];
$r->subprocess_env(hour => $hour);

The page will nicely greet the surfer, picking the greeting based on the current time. Of course, the greeting will be correct only for users located in the same time zone as the server, but this is just a simple example.



    Part I: mod_perl Administration
    Part II: mod_perl Performance
    Part VI: Appendixes