Building the MDB 1: The First Page
We already have a database built of the freedb data (it’s a little out of date, but we can resync that later). So the basic version of the first page is fairly simple. We’ll add a page to display the details of a given CD, and use it as an example of how FireCore works.
To construct our Model we use Class::DBI. We’ll see more detail of what’s possible with it later, but for now all we need to do is use it to set up a basic class to represent the CD table. As we’re using MySQL, we’ve set up our MDB::DBI class as a subclass of Class::DBI::mysql, and told it how to connect to the database. Then we can use the fact that Class::DBI::mysql knows how to query the database for the schema of a table, and the only code we need to write to represent the CD is:
1 2 3 4 5 6 7 | package MDB::CD; use base 'MDB::DBI'; __PACKAGE__->set_up_table('cd'); 1; |
Then we add a line to the Site configuration to create the page to view the cd:
1 2 3 4 5 6 7 8 9 | package MDB::Site; use base 'FireCore::Site::Decl'; sub config_info {qq{ /view/cd gets MDB::CD }} 1; |
Each page that we wish to create for the site will get a line in the config_info.
The sytax for this is quite simple. Here we’re saying that the page “/view/cd” will take an additional argument (e.g. /view/cd/12039) which will represent an MDB::CD object. FireCore will take that argument, validate it, retrieve the MDB::CD with that ID, and pass it to the template.
Then all we need to do is set up the template, which will be “page/view/cd”. Tomorrow we’ll look at setting up some basic abstractions for the pages, but for now we’ll just create a simple HTML page.
FireCore automatically creates header and footer templates that will surround each page, so we don’t need to worry about those, other than to set the page time, so we create a template like:
[% META browser_title = "CD details" %] <h1>[% cd.title %]</h1> <h2>[% cd.artist %]</h2> <p>Length: [% cd.length %]</p>
FireCore uses Template::Toolkit as its templating engine, so we enclose our template directives inside [% %]. As we get passed an MDB::CD object this will be available as ‘cd’ inside the template. Because it’s a Class::DBI object, it will automatically have all the columns of the table available as methods on the object. So to print the title of the CD, we simply say: [% cd.title %]. Now we can visit our CD page and make sure everything looks OK.
The most obvious thing missing now is track information. That lives in a different table, so we need to set up a Track class:
1 2 3 4 5 6 7 | package MDB::Track; use base 'MDB::DBI'; __PACKAGE__->set_up_table('track'); 1; |
Simple. And then, we need to tell the CD class that it has a relationship with the Track class (Current versions of MySQL don’t store this sort of information in the schema, so we can’t auto-detect this):
1 2 3 4 5 6 7 8 | package MDB::CD; use base 'MDB::DBI'; __PACKAGE__->set_up_table('cd'); __PACKAGE__->has_many(tracks => 'MDB::Track'); 1; |
The only addition is line 6, where we tell the CD class to create a method ‘tracks’ which will return a list of all tracks whose ‘cd’ column is the same as our primary key: i.e. it will execute the SQL:
SELECT * FROM track WHERE cd = $cdid
Template Toolkit gives us a looping construct that lets us then insert all the tracks into our template (ordered, of course, by their position on the CD):
<p>Tracks: <ol> [% FOREACH track = cd.tracks.sort('position') %] <li>[% track.title %]</li> [% END %] </ol> </p>
And now we have our simple CD details page. Beyond setting up some basic Class::DBI representations in a purely declarative manner, note that we didn’t write a single line of Perl code. In fact, once you have your tables all mapped in this manner, which in practice is usually part of the set-up phase of the system, rather than done piece by piece like this, you can create quite a lot of your site without ever writing any Perl.