]> git.decadent.org.uk Git - maypole.git/blobdiff - doc/About.pod
use Maypole::Constants;
[maypole.git] / doc / About.pod
index 60c3ab7ec772ceede1cd154a4d33cfafcbd51f3e..3600a9476dcc01e3db038fd04ebff6fc3ea2c1dd 100644 (file)
 
 =head1 Introduction to the Maypole Request Model
 
-=head2 What is MVC for web applications?
+This chapter serves as a gentle introduction to Maypole and setting up
+Maypole applications. We look at Maypole is, how to get it up and
+running, and how to start thinking about building Maypole applications.
 
 =head2 What is Maypole?
 
+Presumably you have some idea of what Maypole is all about, or otherwise
+you wouldn't be reading this manual. But Maypole is good at many
+different things, and you may have accidentally focussed on one aspect
+of Maypole while missing the big picture.
+
+For instance, you may know that Maypole is extremely good at putting web
+front-ends onto databases. This is true, but it's only a part of what
+Maypole does. You may have heard that Maypole is a web application
+framework, which is true, but it doesn't mean very much. There are a
+huge number of things that Maypole can do, because it's very much a
+blank slate. You can make it do what you will. In this manual, we'll be
+making it act as a front-end to a database, as a social network site, as
+an intranet portal, and many other things besides. It is a framework.
+
+I like to think that Maypole is a way of going from a URL to a method
+call to some output. If you have a URL like C</product/order/12>,
+Maypole is a way of having it load up product number 12, call an
+C<order> method, and produce a page about what it's just done. The
+reason Maypole is such a big deal is because it does all this for you.
+You no longer have to care about your web server. You hardly have to
+care about your database. You don't have to care about templating
+modules, parsing CGI parameters, or anything else. You only need to care
+about business logic, and the business logic in this instance is how you
+C<order> a product, and what you need to display about it once you've
+done so. This is what programming should be: only caring about the work
+that distinguishes one program from another.
+
+It does this using a technique called MVC for web applications.
+
+=head2 What is MVC for web applications?
+
+Maypole was originally called C<Apache::MVC>, reflecting its basis in
+the Model-View-Controller design pattern. (I had to change it firstly
+because Maypole isn't tied to Apache, and secondly because
+C<Apache::MVC> is a really dull name.) It's the same design pattern that
+forms the foundation of similar projects in other languages, such as
+Java's Struts framework.
+
+This design pattern is found primarily in graphical applications; the
+idea is that you have a Model class which represents and manipulates
+your data, a View class which is responsible for displaying that data to
+the user, and a Controller class which controls the other classes in
+response to events triggered by the user. This analogy doesn't
+correspond precisely to a web-based application, but we can take an
+important principle from it. As Andy Wardley explains:
+
+    What the MVC-for-the-web crowd are really trying to achieve is a clear
+    separation of concerns.  Put your database code in one place, your 
+    application code in another, your presentation code in a third place.  
+    That way, you can chop and change different elements at will,
+    hopefully without affecting the other parts (depending on how well your
+    concerns are separated, of course).  This is common sense and good practice.
+    MVC achieves this separation of concerns as a by-product of clearly 
+    separating inputs (controls) and outputs (views). 
+
+This is what Maypole does. It has a number of database drivers, a number
+of front-end drivers and a number of templating presentation drivers.
+In common cases, Maypole provides precisely what you need for all of
+these areas, and you get to concentrate on writing just the business
+logic of your application. This is one of the reasons why Maypole lets
+you develop so rapidly: because most of the time, you don't need to do
+any development at all.
+
+=head2 Installing Maypole
+
+The first thing you're going to need to do to get Maypole running is to
+install it. Maypole needs an absolute shedload of Perl modules from CPAN
+to do its job. I am unrepentant about this. Maypole does a lot of work,
+so that you don't have to. This is called code re-use, and if we're
+serious about code re-use, then Maypole should be re-using as much code
+as possible in terms of Perl modules. In another sense, this gives the
+impression that Maypole doesn't actually do all that much itself,
+because all it's doing is gluing together already-existing code. Well,
+welcome to code re-use.
+
+The downside of code re-use is, of course, that you then have to install
+a shedload of Perl modules from CPAN. If you're using OpenBSD or
+FreeBSD, the wonderful ports system will be your friend. There's a
+Maypole port in C<p5-Maypole>. Just type C<make install>.
+
+Debian users, hang in there. There's a package coming.
+
+For other Unices, the L<CPANPLUS> or C<CPAN> modules will help with
+this. If you don't have C<CPANPLUS> installed, my recommendation is to
+use C<perl -MCPAN -e install CPANPLUS> to install it and then throw
+C<CPAN.pm> away. In any case, one of these two should get all that
+Maypole needs:
+
+    % perl -MCPANPLUS -e 'install Maypole'
+    % perl -MCPAN -e 'install Maypole'
+
+I don't know if Maypole works on Windows. I'm not sure I care.
+
+You're also going to need a database server and a web server. For
+databases, I recommend SQLite (if you install the C<DBD::SQLite> module,
+you get the SQLite library for free) for prototyping and mysql for
+production; heavier duty users should use Postgresql or Oracle - Maypole
+should be happy with them all. Maypole is happiest when running under
+Apache C<mod_perl>, with the C<Apache::Request> module installed, but as
+I said, it is a blank slate, and everything is customizable. There is a
+C<CGI::Maypole> frontend available to run as a standalone CGI script.
+
+=head2 The Beer Database example
+
+Throughout this manual, we're going to be referring back to a particular
+application so that we can give concrete examples for the concepts we're
+talking about. We could say "C<related_accessors> returns a list of
+accessors which can be called to return a list of objects in a has-a
+relationship to the original", or we could say "if we call
+C<related_accessors> on while viewing C<brewery>, it returns C<beers>,
+because we can call C<beers> on a C<brewery> object to get a list of
+that berwery's beers." 
+
+Because Maypole is all about beer. If you look carefully, you can
+probably see men playing cricket on the village green. The first
+ever Maypole application was written to help me keep track of the many
+different ales available in my area - their styles, their tastes, their
+breweries, prices and so on. Then the more I thought about it, the more
+I thought it was a particularly good data model for demonstrating
+different kinds of database relationships.
+
+We have a C<brewery> table, which has several C<beer>s. We'll call this
+a has-many relationship. The beers each have a C<style>; styles are
+stored in a separate table, so C<beer> has-a C<style>. Beers are in
+several pubs and a pub has several beers, so beers and pubs are in a
+many-to-many relationship. We use a link table called C<handpump> to
+relate pubs to beers.
+
+All in all, this gives us a schema like the following:
+
+    create table brewery (
+        id int not null auto_increment primary key,
+        name varchar(30),
+        url varchar(50),
+        notes text
+    );
+
+    create table beer (
+        id int not null auto_increment primary key,
+        brewery integer,
+        style integer, 
+        name varchar(30),
+        url varchar(120),
+        score integer(2),
+        price varchar(12),
+        abv varchar(10),
+        notes text
+    );
+
+    create table handpump (
+        id int not null auto_increment primary key,
+        beer integer,
+        pub integer
+    );
+
+    create table pub (
+        id int not null auto_increment primary key,
+        name varchar(60),
+        url varchar(120),
+        notes text
+    );
+
+    create table style (
+        id int not null auto_increment primary key,
+        name varchar(60),
+        notes text
+    );
+
+If you have C<DBD::SQLite> available, then a database like this will
+be created when Maypole was installed. Let's now see how to set it up
+with a web interface.
+
+=head2 Setting up Maypole
+
+The first thing we need for a Maypole interface to a database is to
+have a database. If you don't have one, now would be a good time to
+create one, using the schema above.
+
+The next thing we need is a module which is going to do all the work.
+Thankfully, it doesn't need to do B<all> the work itself. It's going to be a 
+subclass of C<Maypole> or a Maypole front-end like C<Apache::MVC>. 
+
+Here's the driver class for our beer database application. We're not
+going to go into much detail about it here; we'll do that in L<Beer.pod>.
+For now, simply admire its brevity, as you realise this is all the code
+you need to write for a simple database front-end:
+
+    package BeerDB;
+    use base 'Apache::MVC';
+    BeerDB->setup("dbi:SQLite:t/beerdb.db");
+    BeerDB->config->{uri_base} = "http://localhost/beerdb/";
+    BeerDB->config->{rows_per_page} = 10;
+    BeerDB->config->{display_tables} = [qw[beer brewery pub style]];
+    BeerDB::Brewery->untaint_columns( printable => [qw/name notes url/] );
+    BeerDB::Style->untaint_columns( printable => [qw/name notes/] );
+    BeerDB::Beer->untaint_columns(
+        printable => [qw/abv name price notes/],
+        integer => [qw/style brewery score/],
+        date => [ qw/date/],
+    );
+
+    use Class::DBI::Loader::Relationship;
+    BeerDB->config->{loader}->relationship($_) for (
+        "a brewery produces beers",
+        "a style defines beers",
+        "a pub has beers on handpumps");
+    1;
+
+This defines the C<BeerDB> application, which, as it inherits from 
+C<Apache::MVC>, will be a mod_perl handler. This means we need to
+tell the Apache configuration about it:
+
+    <Location /beerdb>
+        SetHandler perl-script
+        PerlHandler BeerDB
+    </Location>
+
+And now we need some templates. As we'll see in the chapter on views,
+L<View.pod>, there are several types of template. We're going to copy
+the whole lot from the F<templates/> directory of the Maypole source
+package into the F</beerdb> directory under our web root.
+
+And that's it. We should now be able to go to C<http://localhost/beerdb/>
+and see a menu of things to browse; C<http://localhost/beerdb/beer/list>
+will give a list of beers. There might not be any yet. There's a box
+that lets you add them.
+
+If you have any problems getting to this point, you might want to look
+at L<http://wiki.simon-cozens.org/index.cgi?InstallationIssues>.
+
+Play about with the site. Add some beers. Maybe go out and buy some beers
+to review if you need some inspiration. Don't be ill on my carpet.
+
 =head2 Phases of a Maypole request
 
-=head2 The model class
+Now you should have a feel for what Maypole can do. The important thing
+to know at this point is that this is by no means B<all> that Maypole
+can do. What you've seen in the beer database example is all that Maypole
+can do if you don't customize it at all.
+
+Remember that, for instance, we don't ever tell Maypole what tables our
+database has, or what columns each table has. We don't tell Maypole what
+those tables should be called or how to display them. We don't tell Maypole
+what to do - that we want to list, search, edit and delete beers and breweries.
+Maypole just works that out for itself. We can customize it and have Maypole
+do all sorts of interesting things with our database, and most of the rest
+of this manual will be about how to do that.
+
+In order to do that, we need to look at what Maypole's actually doing.
+
+As mentioned, Maypole is responsible for turning a URL into an object, a
+method call, and some templated output. Here's a handy diagram to
+explain how it does that:
+
+=for html
+<IMG SRC="maypole_process2.png">
+
+Maypole's process revolves around the concept of the Maypole request
+object. This is a little like Apache's request object, but at a much
+higher level - in fact, in C<mod_perl>-based Maypole front-ends, the
+Apache request object is incorporated in the Maypole request object. All
+that Maypole does is gradually flesh out this object until it contains
+something in the C<output> member, and then it is dispatched back to the
+front-end for output.
+
+So to start with, we take the Apache request (or CGI object, or other
+way of isolating what's going on) and break it down. For instance, we
+turn the URL C</beer/view/1> into
+
+    {
+        table => "beer",
+        action => "view",
+        args => [ 1 ]
+    }
+
+Then Maypole will check that C<beer> is a real table, and find the class
+that models it. It also checks whether or not we're allowed to call the
+C<view> method over the network:
+
+    {
+        table => "beer",
+        action => "view",
+        args => [ 1 ],
+        model_class => "BeerDB::Beer"
+    }
+
+Then there's a user-defined authentication method, which by default just
+lets us do anything. Now we hand over to the model class, which loads up
+the object, and decides what template we want to use:
+
+    {
+        table => "beer",
+        action => "view",
+        args => [ ],
+        objects => [ BeerDB::Beer->retrieve(1) ],
+        model_class => "BeerDB::Beer",
+        template => "view"
+    }
 
-=head2 The view class
+Then it calls C<BeerDB::Beer-E<gt>view>, passing in the request object
+as a parameter, and passes the whole lot to the view class for templating.
+In the next two chapters, we'll look at how Maypole's default model and
+view classes generally do what you want them to do.