http://qs321.pair.com?node_id=126092

czarfred has asked for the wisdom of the Perl Monks concerning the following question:

I'm having a lot of trouble with the following code: (bluebox.pm)

package bluebox; use base 'CGI::Application'; use CGI::Carp qw(fatalsToBrowser); use DBI; use strict; sub setup { my $self = shift; $self->mode_param('mode'); $self->start_mode('list'); $self->run_modes( 'list' => \&list, 'view' => \&view, 'edit' => \&edit, 'new' => \&new, 'del' => \&del ); $self->param('dbh' => DBI->connect('dbi:mysql:adb, 'user', 'pass', { +RaiseError => 1, AutoCommit => 0 })); } sub teardown { my $self = shift; $self->param('dbh')->disconnect(); } sub list { my $self = shift; my $q = $self->query(); my $output; my $dbh = $self->param('dbh'); $output .= $q->header(); $output .= $q->start_html(); $output .= "This is the list page.\n"; $output .= $q->end_html; return $output; } sub view { my $self = shift; my $q = $self->query(); my $output; my $dbh = $self->param('dbh'); return $output; } sub edit { my $self = shift; my $q = $self->query(); my $output; my $dbh = $self->param('dbh'); return $output; } sub new { my $self = shift; my $q = $self->query(); my $output; my $dbh = $self->param('dbh'); return $output; } sub del { my $self = shift; my $q = $self->query(); my $output; my $dbh = $self->param('dbh'); return $output; } 1;


And as for the instance script: (bluebox.cgi)

#!/usr/bin/perl -w use bluebox; use strict; my $book = bluebox->new(); $book->run();


AS you can see, I have not implemented the different modes' subs yet (or I just have test prints where it would be), but that shouldn't have anything to do with the problem.

When I run the instance script (on a apache server at localhost, with the module in @INC), I get the following errors:

Can't use string ("bluebox") as a HASH ref while "strict refs" in use +at /usr/lib/perl5/site_perl/5.6.0/CGI/Application.pm line 361.


Does anyone have any ideas? This this something im doing, or is it maybe a bug (seems unlikely).

Also, what the monks here think about CGI::Application? FYI, this is going to eventully turn out to be an online phone book app (this isnt even the framework for the full implementation, just mostly trying out CGI::Application). Am I using CGI::Application in the right way? Any suggestion on the code so far would be greatly appreciated.

Replies are listed 'Best First'.
Re: CGI::Application Error
by chipmunk (Parson) on Nov 18, 2001 at 10:11 UTC
    The problem appears to be in your new method:
    sub new { my $self = shift; my $q = $self->query(); my $output; my $dbh = $self->param('dbh'); return $output; }
    You are shifting the first argument into $self, and then calling methods on it as if it were an object. However, the point of new is to create an object. The first argument is the name of the class, which in this case is 'bluebox'.

    A standard new method might look something like this:

    sub new { my $class = shift; my %data = { 'member data' => 'initial value' }; return bless \%data, $class; }
    This creates a hash with some initial values, blesses the hash as a member of $class, and returns the resulting object.

    In your module, you're inheriting from CGI::Application; you probably want to let CGI::Application create the object.

    sub new { my $class = shift; my $self = $class->SUPER::new(); # call CGI::Application's new meth +od # do your own initialization, as desired }
    I haven't tested this approach with CGI::Application. It depends on CGI::Application being properly written to support inheritance. That means that CGI::Application's new method, when it calls bless, must use whatever class name was passed in, rather than hard-coding 'CGI::Application'.

    Update: P.S. If you don't need to do any extra initialization in the new method, you can simply inherit CGI::Application's new method, rather than defining your own.

      Thanks for everyone's help. All the input helps a lot. I meant to inherit CGI::Application's new, instead of making my own. Thanks all!
Re: CGI::Application Error
by rob_au (Abbot) on Nov 18, 2001 at 10:13 UTC
    A couple of quick things ...

    With CGI::Application, you return a Content-Type header as part of your output string. The production of headers is handled by CGI::Application which defaults to headers of text/html type - This can modified through the use of the $self->header_type() and $self->header_props methods imported from CGI::Application. eg.

    $self->header_props( -cookie => $cgi->cookie( -expires => '+1y', -name => 'cowsnet-auth', -path => '/', -value => \$user ), -uri => '/' ); $self->header_type('redirect');

    Also too, you may want to look at usage of the HTML::Template module for HTML output through the load_tmpl method offered by CGI::Application.

    Onto the specific problem which you are experiencing, the error is being raised within the query method of the CGI::Application module as it attempts to return a CGI object. I believe that this is resulting from the incorrect passing of parameters into the run_mode method in your setup subroutine - Specifically, you need to enclose your run-mode definitions within braces to signify their belonging to a single hash. eg.

    $self->run_modes({ 'list' => 'list', 'view' => 'view', 'edit' => 'edit', 'new' => 'new', 'del' => 'del' });

    As for my personal opinion of CGI::Application, I am a strong proponent of it and have used it extensively within a number of projects, the framework which it offers, reducing my development time enormously. I have also submitted a review of my thoughts on CGI::Application here which may also be of use.

     

    Update

    Read the comments from data64 and chipmunk on your definition of a new method within your class - There is no need to do this (unless you are seeking to change native CGI::Application behaviour), with the ability to define run-time parameters either through the setup method or through parameters passed from your instance script ... See the CGI::Application review/documentation for more on this

     

    Ooohhh, Rob no beer function well without!

Re: CGI::Application Error
by demerphq (Chancellor) on Nov 18, 2001 at 18:37 UTC
    Its a tiny thing, (the other monks have covered it all pretty well) but you might want to use warnings; and to capitalize your package names. Its a convention that lowercase package names are (informally)reserved for perl pragmas.

    Have a quick read through perlman:perlstyle. Even if you dont go along with its suggestions, the points it raises are worthy of consideration.

    Yves / DeMerphq
    --
    Have you registered your Name Space?

Re: CGI::Application Error
by data64 (Chaplain) on Nov 18, 2001 at 10:04 UTC
    I think your "new" method is overriding the one in CGI::Application and that is resulting in no class instance being created.
    Update: See chipmunk's reply. You need to call the constructor for the parent class from your "new" method.
      This is not the case - The CGI::Application module is designed to act as a base for further module building. See the base library command and the method by which it allows modules to call upon methods and functions of the class it inherits.

      Update - Oops, didn't see the module definition there ... Will update my other reply accordingly - I think czarfred may need to have a closer look at the CGI::Application documentation or my review on this one.

       

      Ooohhh, Rob no beer function well without!

        yes, but the "new" in CGI::Application never gets called with the current code.