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

Hi peeps: I've a site written in Perl and am connecting to a MySQL db using Mysql Perl module. Connection works fine - no probs there. Also using strict and CGI::Carp('fatalsToBrowser');

One table in my db only contains 'widgets' for left-hand and right-hand colums for my pages, called up according to a page_id, the selected language of the visitor, etc...

If there's a subroutine name within the 'sub' db field, I want to call that sub from a previously required library.cgi file, else if there's no subroutine specified within the 'sub' db field, print the data that's in the 'title' and 'text' fields.

Here's the code:

##### Get LHC widgets based on $pid my $dbh = Mysql->connect($DBHOST2, $DBDATA2, $DBUSER2, $DBPASS2); my $qry = qq¿SELECT title,text,sub FROM widgets WHERE page_id = '$ +pid' AND user_lang = '$USER_LANG' AND type = 'lefthandcol' ¿; my $result = $dbh->query($qry); while (my @db = $result->fetchrow){ $LHC_OPTIONS .= ($db[2] ne "") ? &{$db[2]}() : qq¿$db[0]:$db[1 +]<BR>¿ ; }

The data in the 'sub' field is just the name of the routine - ie: build_table - no leading ampersand or trailing brackets.

Even though I'm using strict, I've already soft-referenced things without producing an error (I build my menus from flat-file db's and I use the same &{$array[0]}() structure). However, this code just produces a "Premature end of script headers" error.

Can anyone tell me how I can call a subroutine using the value contained within a database?

Replies are listed 'Best First'.
Re: Perl/MySQL - calling sub from name in dbase
by blue_cowdawg (Monsignor) on Oct 18, 2005 at 13:37 UTC
        However, this code just produces a "Premature end of script headers" error.

    That's a rather generic message and could mean most anything. I'd start my search for truth in this case by looking at the server's error logs and see what it really is objecting to before troubleshooting further.

    I've already done what you are trying to do with some success and you're going about it the right way AFAICT. Check the logs.


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: Perl/MySQL - calling sub from name in dbase
by osunderdog (Deacon) on Oct 18, 2005 at 13:39 UTC

    Same way you would call a function from a scalar:

    use strict; my $funcName = 'foo'; no strict 'refs'; &{$funcName}(); use strict 'refs'; sub foo { print "foo\n"; }

    Hazah! I'm Employed!

Re: Perl/MySQL - calling sub from name in dbase
by graff (Chancellor) on Oct 19, 2005 at 02:26 UTC
    If you have a collection of subroutine names stored in a database, and you want a query from the database to trigger a call to a particular subroutine, I would do it this way:
    # define a hash of sub refs, keyed by sub name my %dbsub = ( foo => \&foo, bar => \&bar, baz => \&baz, ); # now run your query, and then: while ( my @db = $result->fetchrow ) { $LHC_OPTIONS .= ( exists( $dbsub{$db[2]} )) ? $dbsub{$db[2]}->() : join(':', @db[0,1]).'<BR>'; }
    Somehow it just feels safer to me, knowning that I'll only attempt a subroutine call when I know the sub is really there.

    Update: on second thought, I would actually prefer the while loop to do something like this:

    while ( my @db = $result->fetchrow ) { if ( exists( $dbsub{$db[2]} )) { $LHC_OPTIONS .= $dbsub{$db[2]}->(); } else { warn "Unknown sub name in DB: $db[2]\n" if ( $db[2] ); $LHC_OPTIONS .= join(':', @db[0,1]).'<BR>'; } }
    The point being, I'd like to know when the database contains something unexpected in the "sub" field. (Of course, since you seem to be running this as a CGI script, you'll either want to make a habit of scanning the web server's error log, or else you'll want this warning to show up some place where you'll be sure to see it.)