Class-DBI-Factory
view release on metacpan or search on metacpan
lib/Class/DBI/Factory.pm view on Meta::CPAN
class = My::Question
# in your script
use Class::DBI::Factory;
my $factory = Class::DBI::Factory->new('./items.conf');
my $question = $factory->retrieve('question', 1);
A very simple mod_perl application:
# in your virtualhost configuration
PerlSetEnv _CDF_CONFIG '/home/conf/cdf.conf'
PerlSetEnv _CDF_SITE_CONFIG '/home/answers/conf/site.conf'
<Location "/answers">
SetHandler perl-script
PerlHandler Class::DBI::Factory::Handler
</Location>
# in /home/answers/conf/cdf.conf
db_type = 'mysql',
db_name = 'qanda',
db_username = 'me',
db_password = 'password',
class = My::Question
class = My::Answer
master_template = 'master.tt2'
template_path = '/home/answers/templates'
default_view = 'welcome'
# in /home/answers/templates/master.tt2
[% PROCESS "views/${view}.tt2" %]
# in /home/answers/templates/views/welcome.tt2
[% IF input.question %]
[% answers = factory.search('answer', 'question', question ) %]
...
[% ELSE %]
[% questions = factory.search('answer', 'question', question ) %]
[% FOREACH q IN questions %]
...
[% END %]
[% END %]
It does get a little more complicated, but CDF comes with a set of five helpers that should make the rest of your job easier too:
=over
=item L<Class::DBI::Factory::Config>
Wraps around Andy Wardley's AppConfig to provide a simple, friendly configuration mechanism for CDF and the rest of your application. This is very likely to be loaded during even the simplest use of CDF, but you can supply your own configuration mech...
=item L<Class::DBI::Factory::Handler>
A fairly comprehensive base class for mod_perl handlers, providing standard ways of retrieving and displaying one or many cdbi objects. It's biased towards the Template Toolkit but you can easily replace that with your preferred templating system. Se...
There is also a rather experimental Class::DBI::Factory::Handler2 that should provide mod_perl 2 compatibility with little or no rewriting. It's in a fragile state at the moment because of fluctuations in the mod_perl and libapreq2 APIs, but later th...
=item L<Class::DBI::Factory::Exception>
Pervasive but fairly simple exception-handling routines for CDF-based applications based on Apache return codes. CDF::Handler uses try/catch for everything, and most of the other classes here will throw a CDF::Exception on error. See C<fail()>, below...
=item L<Class::DBI::Factory::List>
A fairly comprehensive builder and paginater of lists. It's iterator-based, so should be able to paginate most normal CDBI query results. You can also supply search criteria during list construction. See C<list()> and C<list_from()>, below.
=item L<Class::DBI::Factory::Ghost>
'Ghost' objects are cdbi prototypes: each one is associated with a data class but doesn't belong to it. The ghost object will act like the cdbi object in most simple ways: column values can be set and relationships created, but without any effect on ...
=item L<Class::DBI::Factory::Mailer>
This is a simple interface to Email::Send: it can send messages raw or use the factory's Template object to format them, and it will use the factory's configuration settings to decide how email should be sent. See C<email_message> below.
=back
None of these modules is loaded unless you make a call that requires it, and all of them are easily replaced with your own subclass or alternative module. They all have the same sort of endless POD as this one :)
=head2 PERSISTENCE AND CONCURRENCY
The factory object by itself is a fairly lean and simple thing. Once it has loaded your data classes it should add very little overhead. It is designed to load its helpers only when you do something that requires them, and until you do it should be o...
Constructing a factory object can take a little while, though: it has to load all your data classes, establish database connections, and if you're using TT it has to create its Template object. It's possible to do all that in the course of a CGI requ...
CDF::Handler objects are lightweight and short-lived: a new one is constructed to deal with every incoming request. They can be be quick and simple because it's the factory that does all the work. The normal sequence goes like this:
=over
=item 1. Apache directs an incoming request to mod_perl
=item 2. mod_perl causese the creation of a new Handler object to deal with the request.
=item 3. Handler object uses an existing Factory object for session-management, database access, configuration, template-processing machinery and the other resources needed to deal with the request.
=item 4. Handler object returns output to Apache and is destroyed.
=item 5. Factory waits in memory for next request.
=back
This is all made more useful by the fact that each factory is stored with a distinct id. You can keep several factories active in memory at once, each with a different configuration object and therefore its own cache of database handles, connection p...
Because the data classes' normal database-access methods have been replaced with factory calls, this means that you can use the same set of data classes in as many sites as you like. Each time they ask for database access, the factory object will giv...
The factories don't really 'sleep', of course. They're held in a class-data hash in Class::DBI::Factory. When a handler (or data class, or other script) calls CDF->instance to get its factory object, the instance method will consult its input and env...
In most cases, the 'id' associated with the factory will be the name of a website. If you want, you can specify an $ENV{_SITE_TITLE} in Apache's virtualhost definition:
PerlSetEnv _SITE_TITLE = 'mysite.com'
But CDF will fall back on the $ENV{SITE_NAME} that Apache defines for each virtualhost and which will contain the name given to its ServerName directive.
The same mechanism can be adapted any other situation where you want to keep one or more factory objects handy without having to pass them round all the time. The factory id can be specified directly:
my $factory = Class::DBI::Factory->instance('cd_collection');
or based on any environment variable you specify, such as:
( run in 1.398 second using v1.01-cache-2.11-cpan-364913b4093 )