Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Re: MySQL and perl? Or something else?

by Rhandom (Curate)
on Mar 14, 2007 at 20:45 UTC ( [id://604889]=note: print w/replies, xml ) Need Help??


in reply to MySQL and perl? Or something else?

There are numerous frameworks that will help you do this sort of thing. Many of them are a little over the top. One that may fit the job (without getting in your way too much) is CGI::Ex::App which is part of the CGI::Ex suite. The perldoc for CGI::Ex::App has a recipe book example that is fairly basic.

The sample from the perldoc normally puts all of the html in separate files but CGI::Ex::App allows you to rapid prototype by storing the html in the same file as your script using subs called my_step_file_print which is what I have done below.

Just copy the code below into a file in a cgi directory (or mod_perl registry). Change the datebase connection settings returned by the db_conn method. Chmod it 755. Then go to it in a browser. It has all of the parts of a CRUD (create read update delete) interface for the simple recipe records.

The long debug that prints out after the html shows what methods the CGI::Ex::App used to run each step and can be removed by commenting out the post_navigate method.

For more information as to what is going on, you should read the CGI::Ex::App perldoc.

#!/usr/bin/perl -w package Recipe; use strict; use base qw(CGI::Ex::App); use CGI::Ex::Dump qw(debug); use DBI; Recipe->navigate; ###------------------------------------------### sub handle_error { my ($self, $error) = @_; debug $error, $self->dump_history; die $error; } sub post_navigate { # show what happened during development debug shift->dump_history; } sub base_dir_abs { '/var/www/templates' } sub base_dir_rel { 'content' } sub db_conn { ['dbi:mysql:my_db', 'my_user', 'my_pass'] } sub dbh { my $self = shift; if (! $self->{'dbh'}) { my $conn = $self->db_conn; $self->{'dbh'} = DBI->connect(@$conn, {RaiseError => 1}); $self->create_tables if ! grep {/^`?recipe`?$/} ($self->{'dbh' +}->tables); } return $self->{'dbh'}; } sub create_tables { my $self = shift; $self->dbh->do("CREATE TABLE recipe ( id INTEGER UNSIGNED PRIMARY KEY AUTO_INCREMENT, title VARCHAR(50) NOT NULL, ingredients VARCHAR(255) NOT NULL, directions VARCHAR(255) NOT NULL, date_added DATETIME NOT NULL )"); } ###----------------------------------------------------------------### sub main_info_complete { 0 } sub main_hash_swap { my $self = shift; my $s = "SELECT id, title, date_added FROM recipe ORDER BY date_added"; my $data = $self->dbh->selectall_arrayref($s); my @data = map {my %h; @h{qw(id title date_added)} = @$_; \%h} @$d +ata; return { recipies => \@data, }; } ###----------------------------------------------------------------### sub add_file_print { shift->edit_file_print('edit') } sub add_hash_validation { return { 'group order' => [qw(title ingredients directions)], title => { required => 1, max_len => 30, }, ingredients => { required => 1, max_len => 255, }, directions => { required => 1, max_len => 255, }, }; } sub add_finalize { my $self = shift; my $form = $self->form; my $s = "SELECT COUNT(*) FROM recipe WHERE title = ?"; my ($count) = $self->dbh->selectrow_array($s, {}, $form->{'title'} +); if ($count) { $self->add_errors(title => 'A recipe by this title already exi +sts'); return 0; } $s = "INSERT INTO recipe (title, ingredients, directions, date_add +ed) VALUES (?, ?, ?, NOW())"; $self->dbh->do($s, {}, $form->{'title'}, $form->{'ingredients'}, $form->{'directions'}); $self->add_to_form(success => "Recipe added to the database"); return 1; } ###----------------------------------------------------------------### sub edit_skip { shift->form->{'id'} ? 0 : 1 } sub edit_hash_common { my $self = shift; return {} if $self->ready_validate; my $sth = $self->dbh->prepare("SELECT * FROM recipe WHERE id = ?" +); $sth->execute($self->form->{'id'}); my $hash = $sth->fetchrow_hashref; return $hash; } sub edit_hash_validation { my $hash = shift->add_hash_validation(@_); $hash->{'id'} = {required => 1, match => 'm/^\d+$/'}; # check to m +ake sure id is valid return $hash; } sub edit_finalize { my $self = shift; my $form = $self->form; my $s = "SELECT COUNT(*) FROM recipe WHERE title = ? AND id != ?"; my ($count) = $self->dbh->selectrow_array($s, {}, $form->{'title'} +, $form->{'id'}); if ($count) { $self->add_errors(title => 'A recipe by this title already exi +sts'); return 0; } $s = "UPDATE recipe SET title = ?, ingredients = ?, directions = ? + WHERE id = ?"; $self->dbh->do($s, {}, $form->{'title'}, $form->{'ingredients'}, $form->{'directions'}, $form->{'id'}); $self->add_to_form(success => "Recipe updated in the database"); return 1; } ###----------------------------------------------------------------### sub view_skip { shift->edit_skip(@_) } sub view_hash_common { shift->edit_hash_common(@_) } ###----------------------------------------------------------------### sub delete_skip { shift->edit_skip(@_) } sub delete_info_complete { 1 } sub delete_finalize { my $self = shift; $self->dbh->do("DELETE FROM recipe WHERE id = ?", {}, $self->form- +>{'id'}); $self->add_to_form(success => "Recipe deleted from the database"); return 1; } #File: /var/www/templates/content/recipe/main.html ### -------------------------------------------- sub main_file_print { return \ q{ <html> <head> <title>Recipe DB</title> </head> <h1>Recipe DB</h1> [% IF success %]<span style="color:darkgreen"><h2>[% success %]</h2></ +span>[% END %] <table style="border:1px solid blue"> <tr><th>#</th><th>Title</th><th>Date Added</th></tr> [% FOR row IN recipies %] <tr> <td>[% loop.count %].</td> <td><a href="[% script_name %]/view?id=[% row.id %]">[% row.title %] +</a> (<a href="[% script_name %]/edit?id=[% row.id %]">Edit</a>) </td> <td>[% row.date_added %]</td> </tr> [% END %] <tr><td colspan=2 align=right><a href="[% script_name %]/add">Add new +recipe</a></td></tr> </table> </html> }; } #File: /var/www/templates/content/recipe/edit.html ### -------------------------------------------- sub edit_file_print { return \ q{ <html> <head> <title>[% step == 'add' ? "Add" : "Edit" %] Recipe</title> </head> <h1>[% step == 'add' ? "Add" : "Edit" %] Recipe</h1> <form method=post name=[% form_name %]> <input type=hidden name=step> <table> [% IF step != 'add' ~%] <tr> <td><b>Id:</b></td><td>[% id %]</td></tr> <input type=hidden name=id> </tr> <tr> <td><b>Date Added:</b></td><td>[% date_added %]</td></tr> </tr> [% END ~%] <tr> <td valign=top><b>Title:</b></td> <td><input type=text name=title> <span style='color:red' id=title_error>[% title_error %]</span>< +/td> </tr> <tr> <td valign=top><b>Ingredients:</b></td> <td><textarea name=ingredients rows=10 cols=40 wrap=physical></texta +rea> <span style='color:red' id=ingredients_error>[% ingredients_erro +r %]</span></td> </tr> <tr> <td valign=top><b>Directions:</b></td> <td><textarea name=directions rows=10 cols=40 wrap=virtual></textare +a> <span style='color:red' id=directions_error>[% directions_error +%]</span></td> </tr> <tr> <td colspan=2 align=right> <input type=submit value="[% step == 'add' ? 'Add' : 'Update' %] +"></td> </tr> </table> </form> (<a href="[% script_name %]">Main Menu</a>) [% IF step != 'add' ~%] (<a href="[% script_name %]/delete?id=[% id %]">Delete this recipe</ +a>) [%~ END %] [% js_validation %] </html> }; } #File: /var/www/templates/content/recipe/view.html ### -------------------------------------------- sub view_file_print { return \ q{ <html> <head> <title>[% title %] - Recipe DB</title> </head> <h1>[% title %]</h1> <h3>Date Added: [% date_added %]</h3> <h2>Ingredients</h2> [% ingredients %] <h2>Directions</h2> [% directions %] <hr> (<a href="[% script_name %]">Main Menu</a>) (<a href="[% script_name %]/edit?id=[% id %]">Edit this recipe</a>) </html> }; }


my @a=qw(random brilliant braindead); print $a[rand(@a)];

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://604889]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (4)
As of 2024-04-25 13:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found